import datetime
import uuid
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse

from ..models.anomaly import Anomaly, UpdateAnomaly
from ..utils import MONGODB_DATABASE, check_access, get_sector, get_user_sub, mongodb_connect, send_push_notification

mongodb_client = mongodb_connect()
router = APIRouter(
    prefix="/anomalies",
    tags=["anomalies"],
    responses={404: {"description": "Not found"}},
)

@router.get("")
async def get_anomalies(request: Request):
    """ Get all anomalies """
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        
        anomalies = list(mongodb_client[MONGODB_DATABASE]["anomalies"].find(
            {"status": "open"}, 
            {"_id": 0, "sub": 1, "type": 1, "description": 1, "urgencyLevel": 1, "needHelp": 1, "status": 1, "solution": 1}
        ))
        
        responseObject = {
            "status": "success",
            "endpoint": "GetAnomalies",
            "content": list(anomalies),
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetAnomalies",
            "message": f"Erreur lors de la récupératioin des anomalies {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.get("/closed")
async def get_closed_anomalies(request: Request):
    """ Get all closed anomalies """
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        
        anomalies = list(mongodb_client[MONGODB_DATABASE]["anomalies"].find(
            {"status": "closed"}, 
            {"_id": 0, "sub": 1, "type": 1, "description": 1, "urgencyLevel": 1, "needHelp": 1, "status": 1, "solution": 1}
        ))
        
        responseObject = {
            "status": "success",
            "endpoint": "GetClosedAnomalies",
            "content": list(anomalies),
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetClosedAnomalies",
            "message": f"Erreur lors de la récupératioin des anomalies fermées {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.get("/{sub}")
async def get_anomaly(request: Request, sub: str):
    """ Get anomaly by sub """
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])

        pipeline = [
            {"$match": {"sub": sub}},
            {"$lookup": {
                "from": "interventions",
                "localField": "intervention_sub",
                "foreignField": "sub",
                "as": "intervention"
            }},
            {"$unwind": "$intervention"},
            {"$lookup": {
                "from": "pools",
                "localField": "intervention.pool_sub",
                "foreignField": "sub",
                "as": "pool",
            }},
            {"$unwind": "$pool"},
            {"$lookup": {
                "from": "clients",
                "localField": "pool.client_sub",
                "foreignField": "sub",
                "as": "client",
            }},
            {"$unwind": "$client"},
            {"$lookup": {
                "from": "users",
                "localField": "intervention.user_sub",
                "foreignField": "sub",
                "as": "tech",
            }},
            {"$unwind": "$tech"},
            {"$project": {
                "_id": 0,
                "sub": 1,
                "type": 1,
                "description": 1,
                "urgencyLevel": 1,
                "photo": 1,
                "needHelp": 1,
                "status": 1,
                "solution": 1,
                "created_by": 1,
                "created_at": 1,
                "closed_by": 1,
                "closed_at": 1,
                "intervention": {
                    "sub": 1,
                    "date": 1,
                    "hour": 1
                },
                "client": {
                    "sub": 1,
                    "name": 1
                },
                "tech": {
                    "sub": 1,
                    "firstname": 1,
                    "lastname": 1
                },
            }}
        ]

        anomaly = list(mongodb_client[MONGODB_DATABASE]["anomalies"].aggregate(pipeline))

        if not anomaly:
            responseObject = {
                "status": "error",
                "endpoint": "GetAnomaly",
                "message": f"Anomalie '{sub}' introuvable"
            }
            return JSONResponse(content=responseObject, status_code=404)
        
        if len(anomaly) > 0:
            anomaly = anomaly[0]
        
        responseObject = {
            "status": "success",
            "endpoint": "GetAnomaly",
            "content": anomaly,
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "Get anomaly",
            "message": f"Erreur lors de la récupératioin de l'anomalie {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.post("")
async def create_anomaly(request: Request, anomaly: Anomaly):
    """ Create a new anomaly """
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_user_sub = get_user_sub(auth_token)
        my_user_cursor = mongodb_client[MONGODB_DATABASE]["users"].find_one(
            {"sub": my_user_sub},
            {"_id": 0, "firstname": 1, "lastname": 1, "sector": 1}
        )

        sub = str(uuid.uuid4())
        anomaly_dict = anomaly.model_dump()
        anomaly_dict["sub"] = sub
        anomaly_dict["status"] = "open"
        anomaly_dict["created_by"] = my_user_sub
        anomaly_dict["created_at"] = str(datetime.datetime.now())
        
        mongodb_client[MONGODB_DATABASE]["anomalies"].insert_one(anomaly_dict)

        if "sector" in my_user_cursor:
            users = list(mongodb_client[MONGODB_DATABASE]["users"].find(
                {"$or": [{"roles": "see"}, {"roles": "cs", "sector": my_user_cursor["sector"]}], "sub": {"$ne": my_user_sub}},
                {"_id": 0, "sub": 1}
            ))
        else:
            users = list(mongodb_client[MONGODB_DATABASE]["users"].find(
                {"roles": "see", "sub": {"$ne": my_user_sub}},
                {"_id": 0, "sub": 1}
            ))
        send_push_notification(users, "Anomalie", f"{my_user_cursor['firstname']} {my_user_cursor['lastname']} vient de déclarer une nouvelle anomalie")

        responseObject = {
            "status": "success",
            "endpoint": "CreateAnomaly",
            "sub": sub
        }
        return JSONResponse(content=responseObject, status_code=201)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "CreateAnomaly",
            "message": f"Erreur lors de la création de l'anomalie {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.patch("/{sub}")
async def update_anomaly(request: Request, sub: str, anomaly: UpdateAnomaly):
    """ Update an anomaly """
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        
        anomaly_cursor = mongodb_client[MONGODB_DATABASE]["anomalies"].find_one(
            {"sub": sub},
            {"_id": 0}
        )

        if not anomaly_cursor:
            responseObject = {
                "status": "error",
                "endpoint": "UpdateAnomaly",
                "message": f"Anomalie '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)

        anomaly_dict = anomaly.model_dump()
        if "photo" in anomaly_dict and anomaly_dict["photo"] == None:
            anomaly_dict["photo"] = ""

        anomaly_dict = {key: value for key,
                     value in anomaly_dict.items() if value is not None}
        
        mongodb_client[MONGODB_DATABASE]["anomalies"].update_one(
            {"sub": sub},
            {"$set": anomaly_dict}
        )

        responseObject = {
            "status": "success",
            "endpoint": "UpdateAnomaly",
            "message": "Anomalie mise à jour avec succès",
            "content": anomaly_dict
        }
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "UpdateAnomaly",
            "message": f"Erreur lors de la mise à jour de l'anomalie {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.put("/close/{sub}")
async def close_anomaly(request: Request, sub: str):
    """ Close an anomaly """
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_user_sub = get_user_sub(auth_token)
        
        anomaly_cursor = mongodb_client[MONGODB_DATABASE]["anomalies"].find_one(
            {"sub": sub},
            {"_id": 0}
        )

        if not anomaly_cursor:
            responseObject = {
                "status": "error",
                "endpoint": "CloseAnomaly",
                "message": f"Anomalie '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)

        mongodb_client[MONGODB_DATABASE]["anomalies"].update_one(
            {"sub": sub},
            {"$set": {"status": "closed", "solution": "Anomalie fermée", "closed_by": my_user_sub, "closed_at": str(datetime.datetime.now())}}
        )

        responseObject = {
            "status": "success",
            "endpoint": "CloseAnomaly",
            "message": "Anomalie fermée avec succès",
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "CloseAnomaly",
            "message": f"Erreur lors de la fermeture de l'anomalie {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)