import datetime
import uuid
from fastapi import APIRouter, Request, Query
from fastapi.responses import JSONResponse
from ..models.interventions import Intervention, RescheduleIntervention, UpdateIntervention
from ..utils import MONGODB_DATABASE, get_roles, get_sector, get_user_sub, mongodb_connect, check_access
from pymongo import ASCENDING

mongodb_client = mongodb_connect()
router = APIRouter(
    prefix="/interventions",
    tags=["interventions"],
    responses={404: {"description": "Not found"}},
)

@router.post("")
async def create_intervention(request: Request, intervention: Intervention):
    """Create intervention."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["see"])

        pool_cursor = mongodb_client[MONGODB_DATABASE]["pools"].find_one(
            {"sub": intervention.pool_sub},
            {"_id": 0, "client_sub": 1}
        )

        client_cursor = mongodb_client[MONGODB_DATABASE]["clients"].find_one(
            {"sub": pool_cursor["client_sub"]},
            {"_id": 0, "maintenance_info": 1, "user_sub": 1}
        )
        
        intervention_dict = {}
        intervention_dict["sub"] = str(uuid.uuid4())
        intervention_dict["date"] = intervention.date
        intervention_dict["hour"] = intervention.hour
        intervention_dict["pool_sub"] = intervention.pool_sub
        intervention_dict["duration"] = client_cursor["maintenance_info"]["duration"]
        intervention_dict["user_sub"] = client_cursor["user_sub"]

        mongodb_client[MONGODB_DATABASE]["interventions"].insert_one(
            intervention_dict
        )

        responseObject = {
            "status": "success",
            "endpoint": "CreateIntervention",
            "message": "Intervention créée avec succès"
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "CreateIntervention",
            "message": f"Error lors de la création de l'intervention: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.get("/{sub}")
async def get_intervention(request: Request, sub: str):
    """Get intervention."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])

        pipeline = [
            {"$match": {"sub": sub}},
            {
                "$lookup": {
                    "from": "pools",
                    "localField": "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": "client.user_sub",
                    "foreignField": "sub",
                    "as": "tech",
                }
            },
            {"$unwind": "$tech"},
            {
                "$lookup": {
                    "from": "anomalies",
                    "localField": "sub",
                    "foreignField": "intervention_sub",
                    "as": "anomalies"
                }
            },
            {
                "$project": {
                    "_id": 0,
                    "sub": 1,
                    "date": 1,
                    "hour": 1,
                    "duration": 1,
                    "state": 1,
                    "started_at": 1,
                    "closed_at": 1,
                    "startingPhoto": 1,
                    "endingPhoto": 1,
                    "step1": 1,
                    "step2": 1,
                    "step3": 1,
                    "chlore": 1,
                    "ph": 1,
                    "stabilisant": 1,
                    "compteur": 1,
                    "report": 1,
                    "note": 1,
                    "pool": {
                        "sub": 1,
                        "description": 1,
                        "gps": 1,
                        "photo": 1,
                    },
                    "client": {
                        "sub": 1,
                        "name": 1,
                        "client_type": 1,
                        "address": 1,
                        "gps": 1,
                        "access": 1,
                        "access_note": 1,
                        "contacts": 1,
                        "syndic": 1,
                        "maintenance_info": 1,
                    },
                    "tech": {
                        "sub": 1,
                        "firstname": 1,
                        "lastname": 1,
                    },
                    "anomalies": {
                        "sub": 1,
                        "type": 1,
                        "description": 1,
                        "status": 1,
                        "urgencyLevel": 1,
                        "solution": 1,
                    },
                }
            }
        ]

        interventions = list(mongodb_client[MONGODB_DATABASE]["interventions"].aggregate(pipeline))

        responseObject = {
            "status": "success",
            "endpoint": "GetInterventionList",
            "message": "Interventions récupéré avec succès",
            "content": interventions[0]
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetUserList",
            "message": f"Error lors de la récupération de l'interventions: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)

@router.get("/date/{date}")
async def get_intervention_list_by_date(request: Request, date: str):
    """Get all interventions by date."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_user_sub = get_user_sub(auth_token)
        my_roles = get_roles(auth_token)

        if any(role in ['ae1', 'ae2', 'ae3', 'ae4'] for role in my_roles):
            pipeline = [
                {"$match": {"date": date, "user_sub": my_user_sub}},
                {
                    "$lookup": {
                        "from": "pools",
                        "localField": "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": "client.user_sub",
                        "foreignField": "sub",
                        "as": "tech",
                    }
                },
                {"$unwind": "$tech"},
                {
                    "$project": {
                        "_id": 0,
                        "sub": 1,
                        "date": 1,
                        "hour": 1,
                        "duration": 1,
                        "state": 1,
                        "pool.sub": 1,
                        "pool.description": 1,
                        "client.sub": 1,
                        "client.name": 1,
                        "tech.sub": 1,
                        "tech.firstname": 1,
                        "tech.lastname": 1,
                    }
                }
            ]
        elif any(role in ['formateur', 'cs'] for role in my_roles):
            my_sector = get_sector(auth_token)
            pipeline = [
                {
                    "$lookup": {
                        "from": "pools",
                        "localField": "pool_sub",
                        "foreignField": "sub",
                        "as": "pool"
                    }
                },
                {"$unwind": "$pool"},
                {
                    "$lookup": {
                        "from": "clients",
                        "localField": "pool.client_sub",
                        "foreignField": "sub",
                        "as": "client"
                    }
                },
                {"$unwind": "$client"},
                {
                    "$match": {"client.sector": {"$eq": my_sector}, "date": date}
                },
                {
                    "$lookup": {
                        "from": "users",
                        "localField": "client.user_sub",
                        "foreignField": "sub",
                        "as": "tech",
                    }
                },
                {"$unwind": "$tech"},
                {
                    "$project": {
                        "_id": 0,
                        "sub": 1,
                        "date": 1,
                        "hour": 1,
                        "duration": 1,
                        "state": 1,
                        "pool.sub": 1,
                        "pool.description": 1,
                        "client.sub": 1,
                        "client.name": 1,
                        "tech.sub": 1,
                        "tech.firstname": 1,
                        "tech.lastname": 1,
                    }
                }
            ]
        else:
            pipeline = [
                {"$match": {"date": date}},
                {
                    "$lookup": {
                        "from": "pools",
                        "localField": "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": "client.user_sub",
                        "foreignField": "sub",
                        "as": "tech",
                    }
                },
                {"$unwind": "$tech"},
                {
                    "$project": {
                        "_id": 0,
                        "sub": 1,
                        "date": 1,
                        "hour": 1,
                        "duration": 1,
                        "state": 1,
                        "chlore": 1,
                        "ph": 1,
                        "stabilisant": 1,
                        "pool.sub": 1,
                        "pool.description": 1,
                        "client.sub": 1,
                        "client.name": 1,
                        "tech.sub": 1,
                        "tech.firstname": 1,
                        "tech.lastname": 1,
                    }
                }
            ]

        interventions = list(mongodb_client[MONGODB_DATABASE]["interventions"].aggregate(pipeline))

        responseObject = {
            "status": "success",
            "endpoint": "GetInterventionList",
            "message": "Liste des interventions récupéré avec succès",
            "content": list(interventions)
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetUserList",
            "message": f"Error lors de la récupération des interventions: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)

@router.get("/month/{month}")
async def get_intervention_list_by_month(
    request: Request, 
    month: str, 
    limit: int = Query(default=100, ge=1, le=1000),
    skip: int = Query(default=0, ge=0)
):
    """Get all interventions by month."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_user_sub = get_user_sub(auth_token)
        my_roles = get_roles(auth_token)

        # Create index for faster queries
        mongodb_client[MONGODB_DATABASE]["interventions"].create_index([("date", ASCENDING)])

        base_query = {"date": {"$regex": f"^{month}"}}
        projection = {"_id": 0, "sub": 1, "date": 1, "hour": 1, "duration": 1, "state": 1, "chlore": 1, "ph": 1, "stabilisant": 1}

        if any(role in ['ae1', 'ae2', 'ae3', 'ae4'] for role in my_roles):
            base_query["user_sub"] = my_user_sub
        elif any(role in ['formateur', 'cs'] for role in my_roles):
            my_sector = get_sector(auth_token)
            # Pre-fetch client subs for the sector
            client_subs = set(mongodb_client[MONGODB_DATABASE]["clients"].distinct("sub", {"sector": my_sector}))
            pool_subs = set(mongodb_client[MONGODB_DATABASE]["pools"].distinct("sub", {"client_sub": {"$in": list(client_subs)}}))
            base_query["pool_sub"] = {"$in": list(pool_subs)}

        # Use find instead of aggregate
        interventions = list(mongodb_client[MONGODB_DATABASE]["interventions"]
                             .find(base_query, projection)
                             .sort("date", 1)
                             .skip(skip)
                             .limit(limit))

        responseObject = {
            "status": "success",
            "endpoint": "GetInterventionList",
            "message": "Liste des interventions récupéré avec succès",
            "content": interventions
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetUserList",
            "message": f"Error lors de la récupération des interventions: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.get("/week/{start_date}/{end_date}")
async def get_intervention_list_by_week(request: Request, start_date: str, end_date: str):
    """Get all interventions for a specific week."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_user_sub = get_user_sub(auth_token)
        my_roles = get_roles(auth_token)

        if any(role in ['ae1', 'ae2', 'ae3', 'ae4'] for role in my_roles):
            pipeline = [
                {"$match": {
                    "date": {"$gte": start_date, "$lte": end_date},
                    "user_sub": my_user_sub
                }},
                {
                    "$lookup": {
                        "from": "pools",
                        "localField": "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": "client.user_sub",
                        "foreignField": "sub",
                        "as": "tech",
                    }
                },
                {"$unwind": "$tech"},
                {
                    "$project": {
                        "_id": 0,
                        "sub": 1,
                        "date": 1,
                        "hour": 1,
                        "duration": 1,
                        "state": 1,
                        "chlore": 1,
                        "ph": 1,
                        "stabilisant": 1,
                        "pool.sub": 1,
                        "pool.description": 1,
                        "client.sub": 1,
                        "client.name": 1,
                        "tech.sub": 1,
                        "tech.firstname": 1,
                        "tech.lastname": 1,
                    }
                }
            ]
        elif any(role in ['formateur', 'cs'] for role in my_roles):
            my_sector = get_sector(auth_token)
            pipeline = [
                {
                    "$lookup": {
                        "from": "pools",
                        "localField": "pool_sub",
                        "foreignField": "sub",
                        "as": "pool"
                    }
                },
                {"$unwind": "$pool"},
                {
                    "$lookup": {
                        "from": "clients",
                        "localField": "pool.client_sub",
                        "foreignField": "sub",
                        "as": "client"
                    }
                },
                {"$unwind": "$client"},
                {
                    "$match": {
                        "client.sector": {"$eq": my_sector},
                        "date": {"$gte": start_date, "$lte": end_date}
                    }
                },
                {
                    "$lookup": {
                        "from": "users",
                        "localField": "client.user_sub",
                        "foreignField": "sub",
                        "as": "tech",
                    }
                },
                {"$unwind": "$tech"},
                {
                    "$project": {
                        "_id": 0,
                        "sub": 1,
                        "date": 1,
                        "hour": 1,
                        "duration": 1,
                        "state": 1,
                        "chlore": 1,
                        "ph": 1,
                        "stabilisant": 1,
                        "pool.sub": 1,
                        "pool.description": 1,
                        "client.sub": 1,
                        "client.name": 1,
                        "tech.sub": 1,
                        "tech.firstname": 1,
                        "tech.lastname": 1,
                    }
                }
            ]
        else:
            pipeline = [
                {"$match": {"date": {"$gte": start_date, "$lte": end_date}}},
                {
                    "$lookup": {
                        "from": "pools",
                        "localField": "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": "client.user_sub",
                        "foreignField": "sub",
                        "as": "tech",
                    }
                },
                {"$unwind": "$tech"},
                {
                    "$project": {
                        "_id": 0,
                        "sub": 1,
                        "date": 1,
                        "hour": 1,
                        "duration": 1,
                        "state": 1,
                        "chlore": 1,
                        "ph": 1,
                        "stabilisant": 1,
                        "pool.sub": 1,
                        "pool.description": 1,
                        "client.sub": 1,
                        "client.name": 1,
                        "tech.sub": 1,
                        "tech.firstname": 1,
                        "tech.lastname": 1,
                    }
                }
            ]

        interventions = list(mongodb_client[MONGODB_DATABASE]["interventions"].aggregate(pipeline))

        responseObject = {
            "status": "success",
            "endpoint": "GetInterventionListByWeek",
            "message": "Liste des interventions récupérée avec succès",
            "content": interventions
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetInterventionListByWeek",
            "message": f"Erreur lors de la récupération des interventions: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)

@router.put("/intervention/start/{sub}")
async def start_intervention(request: Request, sub: str):
    """Start intervention."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])

        start_dict = {"state": "doing", "started_at": str(datetime.datetime.now())}

        mongodb_client[MONGODB_DATABASE]["interventions"].update_one(
            {"sub": sub},
            {"$set": start_dict}
        )

        responseObject = {
            "status": "success",
            "endpoint": "StartIntervention",
            "message": "Interventions démarrée avec succès",
            "content": start_dict
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetUserList",
            "message": f"Error lors du démarrage de l'interventions: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.patch("/{sub}")
async def update_intervention(request: Request, sub: str, intervension: UpdateIntervention):
    """Update intervention."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])

        intervention_cursor = mongodb_client[MONGODB_DATABASE]["interventions"].find_one(
            {"sub": sub},
            {"_id": 0}
        )

        if not intervention_cursor:
            responseObject = {
                "status": "error",
                "endpoint": "UpdateIntervention",
                "message": f"Intervention '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)

        intervension_dict = intervension.model_dump()
        if "startingPhoto" in intervension_dict and intervension_dict["startingPhoto"] == None:
            intervension_dict["startingPhoto"] = ""
        if "endingPhoto" in intervension_dict and intervension_dict["endingPhoto"] == None:
            intervension_dict["endingPhoto"] = ""

        intervension_dict = {key: value for key,
                     value in intervension_dict.items() if value is not None}
        if "step3" in intervension_dict and intervension_dict["step3"] == True:
            intervension_dict["state"] = "done"
            intervension_dict["closed_at"] = str(datetime.datetime.now())
        
        mongodb_client[MONGODB_DATABASE]["interventions"].update_one(
            {"sub": sub},
            {"$set": intervension_dict}
        )

        responseObject = {
            "status": "success",
            "endpoint": "UpdateIntervention",
            "message": "Interventions mise à jour avec succès",
            "content": intervension_dict
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "UpdateIntervention",
            "message": f"Error lors de la mise à jour de l'interventions: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.delete("/{sub}")
async def delete_intervention(request: Request, sub: str):
    """Delete intervention."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["see"])
        
        result = mongodb_client[MONGODB_DATABASE]["interventions"].delete_one(
            {"sub": sub}
        )

        if result.deleted_count == 0:
            responseObject = {
                "status": "error",
                "endpoint": "DeleteIntervention",
                "message": f"Intervention '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)
        
        responseObject = {
            "status": "success",
            "endpoint": "DeleteIntervention",
            "message": "Intervention supprimée avec succès"
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "DeleteIntervention",
            "message": f"Error lors de la suppression de l'intervention: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
    
@router.put("/intervention/reschedule/{sub}")
async def reschedule_intervention(request: Request, sub: str, newSchedule: RescheduleIntervention):
    """Reschedule intervention."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_user_sub = get_user_sub(auth_token)

        reschedule_dict = newSchedule.model_dump()

        reschedule_cursor = mongodb_client[MONGODB_DATABASE]["interventions"].update_one(
            {"sub": sub},
            {"$set": reschedule_dict}
        )

        if reschedule_cursor.matched_count == 0:
            responseObject = {
                "status": "error",
                "endpoint": "RescheduleIntervention",
                "message": f"Intervention '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)
        
        if "anomaly_sub" in reschedule_dict:
            date = reschedule_dict["date"].split("-")
            mongodb_client[MONGODB_DATABASE]["anomalies"].update_one(
                {"sub": reschedule_dict["anomaly_sub"]},
                {"$set": {"status": "closed", "solution": f"Intervention reprogrammée pour le {date[2]}-{date[1]}-{date[0]} à {reschedule_dict["hour"]}", "closed_by": my_user_sub, "closed_at": str(datetime.datetime.now())}}
            )

        responseObject = {
            "status": "success",
            "endpoint": "RescheduleIntervention",
            "message": "Intervention reprogrammée avec succès"
        }

        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "RescheduleIntervention",
            "message": f"Error lors de la reprogrammation de l'intervention: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)