from time import time

from fastapi import APIRouter

from app import mongo
from app.utils.response_util import response

router = APIRouter()


@router.get("/", tags=[""])
async def get_departments():
    start_time = time()

    departments = await mongo.departments_collection.find(
        {}, {"_id": False}
    ).sort("id", mongo.asc).to_list(length=None)

    async def build_section_tree(parent_section):
        users = []
        for user in parent_section.get("users", []):
            user_data = await mongo.users_collection.find_one({"id": user["userId"]}, {"_id": False})
            if user_data:
                user["user"] = user_data
                users.append(user)

        parent_section["users"] = users

        children = await mongo.department_sections_collection.find(
            {"parentDepartmentSectionId": parent_section["id"]},
            {"_id": False}
        ).sort("id", mongo.asc).to_list(length=None)

        parent_section["sections"] = []
        for child in children:
            await build_section_tree(child)
            parent_section["sections"].append(child)

    for department in departments:
        top_sections = await mongo.department_sections_collection.find(
            {
                "departmentId": department["id"],
                "$or": [{"parentDepartmentSectionId": None}, {"parentDepartmentSectionId": {"$exists": False}}]
            },
            {"_id": False}
        ).sort("id", mongo.asc).to_list(length=None)

        department["sections"] = []
        for section in top_sections:
            await build_section_tree(section)
            department["sections"].append(section)

    return response({
        "departments": departments
    }, start_time=start_time)


@router.post("/", tags=[""])
async def create_department(params: dict):
    start_time = time()
    data = params["department"]

    data["id"] = await mongo.get_next_id(mongo.departments_collection)
    await mongo.departments_collection.insert_one(data)

    return response({"message": "Департамент создан", "ok": True}, start_time=start_time)


@router.patch("/", tags=[""])
async def update_department(params: dict):
    start_time = time()
    data = params["department"]

    await mongo.departments_collection.update_one({"id": data["id"]}, {"$set": data})
    return response({"message": "Департамент обновлён", "ok": True}, start_time=start_time)


@router.delete("/{department_id}", tags=[""])
async def delete_department(department_id: int):
    start_time = time()

    sections = await mongo.department_sections_collection.find(
        {"departmentId": department_id}, {"_id": False}
    ).to_list(length=None)

    for section in sections:
        await delete_section_recursive(section["id"])

    await mongo.departments_collection.delete_one({"id": department_id})
    return response({"message": "Департамент удалён", "ok": True}, start_time=start_time)


@router.get("/section", tags=[""])
async def get_sections():
    start_time = time()
    department_sections = await mongo.department_sections_collection.find(
        {}, {"_id": False}
    ).sort("id", mongo.asc).to_list(length=None)

    return response({
        "departmentSections": department_sections
    }, start_time=start_time)


@router.post("/section", tags=[""])
async def create_section(params: dict):
    start_time = time()
    data = params["section"]

    if "departmentId" not in data:
        return response({
            "message": "Необходимо выбрать департамент",
            "ok": False
        }, start_time=start_time)

    data["id"] = await mongo.get_next_id(mongo.department_sections_collection)
    await mongo.department_sections_collection.insert_one(data)

    return response({
        "message": "Отдел создан",
        "ok": True
    }, start_time=start_time)


@router.patch("/section", tags=[""])
async def update_section(params: dict):
    start_time = time()
    data = params["section"]

    await mongo.department_sections_collection.update_one({"id": data["id"]}, {"$set": data})
    return response({"message": "Отдел обновлен", "ok": True}, start_time=start_time)


@router.delete("/section/{section_id}", tags=[""])
async def delete_section(section_id: int):
    start_time = time()

    await delete_section_recursive(section_id)
    return response({"message": "Отдел удален", "ok": True}, start_time=start_time)


@router.get("/users/{section_id}", tags=[""])
async def get_available_users(section_id: int):
    start_time = time()

    users = await mongo.users_collection.find(
        {"isDeleted": False}, {"_id": False}
    ).to_list(length=None)

    return response({
        "users": users
    }, start_time=start_time)


@router.post("/users", tags=[""])
async def add_user_to_section(params: dict):
    start_time = time()
    section_id = params["sectionId"]
    user_id = params["userId"]
    is_chief = params.get("isChief", False)

    await mongo.department_sections_collection.update_one(
        {"id": section_id},
        {"$addToSet": {"users": {"userId": user_id, "isChief": is_chief}}}
    )

    return response({
        "message": "Пользователь добавлен в секцию",
        "ok": True
    }, start_time=start_time)


@router.post("/users/delete", tags=[""])
async def delete_user_from_section(params: dict):
    start_time = time()
    section_id = params["sectionId"]
    user_id = params["userId"]

    await mongo.department_sections_collection.update_one(
        {"id": section_id},
        {"$pull": {"users": {"userId": user_id}}}
    )

    return response({
        "message": "Пользователь удалён из секции",
        "ok": True
    }, start_time=start_time)


async def delete_section_recursive(section_id: int):
    children = await mongo.department_sections_collection.find(
        {"parentDepartmentSectionId": section_id}, {"_id": False}
    ).to_list(length=None)

    for child in children:
        await delete_section_recursive(child["id"])

    await mongo.department_sections_collection.delete_one({"id": section_id})
