import uuid
from fastapi import APIRouter, Request

from fastapi.responses import JSONResponse

from ..scheduler import regenerate_interventions_for_client

from ..utils import MONGODB_DATABASE, mongodb_connect, check_access, get_user_sub, get_roles
from ..models.clients import Client, UpdateClient

mongodb_client = mongodb_connect()
router = APIRouter(
    prefix="/clients",
    tags=["clients"],
    responses={404: {"description": "Not found"}},
)


@router.post("")
async def create_client(request: Request, client: Client):
    """Create a new client."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["see"])
        my_user_sub = get_user_sub(auth_token)

        sub = str(uuid.uuid4())
        client_dict = client.model_dump()
        client_dict["sub"] = sub
        client_dict["active"] = True
        client_dict["created_by_sub"] = my_user_sub

        mongodb_client[MONGODB_DATABASE]["clients"].insert_one(client_dict)
        responseObject = {
            "status": "success",
            "endpoint": "CreateClient",
            "message": "Client créé avec succès.",
            "sub": sub
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "CreateClient",
            "message": f"Error lors de l'enregistrement du client: {str(e)}"
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.get("")
async def get_client_list(request: Request):
    """Get all clients."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_sub = get_user_sub(auth_token)
        my_roles = get_roles(auth_token)

        pipeline = [
            {"$match": {"active": True}},
            {
                "$lookup": {
                    "from": "users",
                    "localField": "user_sub",
                    "foreignField": "sub",
                    "as": "tech",
                }
            },
            # {"$unwind": "$tech"},
            {
                "$project": {
                    "_id": 0,
                    "sub": 1,
                    "name": 1,
                    "client_type": 1,
                    "sector": 1,
                    "address": 1,
                    "gps": 1,
                    "tech.sub": 1,
                    "tech.firstname": 1,
                    "tech.lastname": 1,
                    "tech.roles": 1
                }
            }
        ]

        if not any(role in my_roles for role in ["root", "see"]):
            my_sector = mongodb_client[MONGODB_DATABASE]["users"].find_one(
                {"sub": my_sub},
                {"_id": 0, "sector": 1}
            )
            pipeline[0]["$match"]["sector"] = my_sector["sector"]
        
        clients = list(mongodb_client[MONGODB_DATABASE]["clients"].aggregate(
            pipeline))
        responseObject = {
            "status": "success",
            "endpoint": "GetClientList",
            "message": "Liste de clients récupéré avec succès",
            "content": list(clients)
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetClientList",
            "message": f"Error lors de la récupération des clients: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.get("/{sub}")
async def get_client(request: Request, sub: str):
    """Get a client by his sub."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        client = mongodb_client[MONGODB_DATABASE]["clients"].find_one(
            {"sub": sub},
            {"_id": 0}
        )

        if not client:
            responseObject = {
                "status": "error",
                "endpoint": "GetClient",
                "message": f"Client '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)

        responseObject = {
            "status": "success",
            "endpoint": "GetClient",
            "message": f"Client '{sub}' récupéré avec succès",
            "content": client
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetClient",
            "message": f"Error lors de la récupération du client: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.patch("/{sub}")
async def update_client(request: Request, sub: str, client: UpdateClient):
    """update a client by his sub."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["see"])
        client_cursor = mongodb_client[MONGODB_DATABASE]["clients"].find_one(
            {"sub": sub},
            {"_id": 0}
        )

        client_dict = client.model_dump()
        client_dict = {key: value for key,
                       value in client_dict.items() if value is not None}

        if not client_cursor:
            responseObject = {
                "status": "error",
                "endpoint": "UpdateClient",
                "message": f"Client '{sub}' n'existe pas",
            }
            return JSONResponse(content=responseObject, status_code=404)

        mongodb_client[MONGODB_DATABASE]["clients"].update_one(
            {"sub": sub},
            {"$set": client_dict}
        )

        await regenerate_interventions_for_client(sub)

        responseObject = {
            "status": "success",
            "endpoint": "UpdateClient",
            "message": f"Client '{sub}' mis à jour avec succès",
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "UpdateClient",
            "message": f"Error lors de la mise à jour du client: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.delete("/{sub}")
async def disable_client(request: Request, sub: str):
    """Disable a client by his sub."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["see"])
        result = mongodb_client[MONGODB_DATABASE]["clients"].find_one_and_update(
            {"sub": sub, "active": True}, {"$set": {"active": False}}
        )

        if not result:
            responseObject = {
                "status": "error",
                "endpoint": "DisableClient",
                "message": f"Vous n'avez pas le droit d'accès à cette ressource",
            }
            return JSONResponse(content=responseObject, status_code=403)

        responseObject = {
            "status": "success",
            "endpoint": "DisableClient",
            "message": f"Client '{sub}' désactivé avec succès",
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "DisableClient",
            "message": f"Error lors de la désactivation du client: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.put("/{sub}")
async def activate_client(request: Request, sub: str):
    """Activate a client by his sub."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["see"])
        result = mongodb_client[MONGODB_DATABASE]["clients"].find_one_and_update(
            {"sub": sub, "active": False}, {"$set": {"active": True}}
        )

        if not result:
            responseObject = {
                "status": "error",
                "endpoint": "ActivateClient",
                "message": f"Vous n'avez pas le droit d'accès à cette ressource",
            }
            return JSONResponse(content=responseObject, status_code=403)

        responseObject = {
            "status": "success",
            "endpoint": "ActivateClient",
            "message": f"Client '{sub}' activé avec succès",
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "ActivateClient",
            "message": f"Error lors de l'activation du client: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)


@router.get("/archive/list")
async def get_archived_clients(request: Request):
    """Get all archived clients."""
    try:
        auth_token = request.headers["authorization"].replace("Bearer ", "")
        check_access(auth_token, ["*"])
        my_sub = get_user_sub(auth_token)
        my_roles = get_roles(auth_token)

        pipeline = [
            {"$match": {"active": False}},
            {
                "$lookup": {
                    "from": "users",
                    "localField": "user_sub",
                    "foreignField": "sub",
                    "as": "tech",
                }
            },
            # {"$unwind": "$tech"},
            {
                "$project": {
                    "_id": 0,
                    "sub": 1,
                    "name": 1,
                    "client_type": 1,
                    "sector": 1,
                    "address": 1,
                    "gps": 1,
                    "tech.sub": 1,
                    "tech.firstname": 1,
                    "tech.lastname": 1,
                    "tech.roles": 1
                }
            }
        ]

        if not any(role in my_roles for role in ["root", "see"]):
            my_sector = mongodb_client[MONGODB_DATABASE]["users"].find_one(
                {"sub": my_sub},
                {"_id": 0, "sector": 1}
            )
            pipeline[0]["$match"]["sector"] = my_sector["sector"]
        
        clients = list(mongodb_client[MONGODB_DATABASE]["clients"].aggregate(
            pipeline))
        responseObject = {
            "status": "success",
            "endpoint": "GetArchivedClientsList",
            "message": f"Liste de clients archivés récupéré avec succès",
            "content": list(clients)
        }
        return JSONResponse(content=responseObject, status_code=200)
    except Exception as e:
        responseObject = {
            "status": "error",
            "endpoint": "GetArchivedClientList",
            "message": f"Error lors de la récupération des clients: {str(e)}",
        }
        return JSONResponse(content=responseObject, status_code=500)
