# _*_ coding : UTF-8 _*_
# @Time : 2025/01/20 01:30
# @UpdateTime : 2025/01/20 01:30
# @Author : sonder
# @File : department.py
# @Software : PyCharm
# @Comment : 本程序
from typing import Optional

from fastapi import APIRouter, Depends, Query, Path, Request
from fastapi.responses import JSONResponse

from annotation.log import Log
from config.constant import BusinessType
from controller.login import LoginController
from models import Department, Role, DepartmentRole
from schemas.common import BaseResponse
from schemas.department import AddDepartmentParams, GetDepartmentInfoResponse, \
    GetDepartmentListResponse, AddDepartmentRoleParams, GetDepartmentRoleInfoResponse, DeleteDepartmentListParams
from utils.response import Response

departmentAPI = APIRouter(prefix="/department", dependencies=[Depends(LoginController.get_current_user)])


@departmentAPI.post("/add", response_model=BaseResponse, response_class=JSONResponse, summary="新增部门")
@Log(title="新增部门", business_type=BusinessType.INSERT)
async def add_department(request: Request, params: AddDepartmentParams,
                         current_user: dict = Depends(LoginController.get_current_user)):
    parent_id = current_user.get("department_id")
    if not params.parent_id:
        params.parent_id = parent_id
    department = await Department.create(
        name=params.name,
        parent_id=params.parent_id,
        principal=params.principal,
        phone=params.phone,
        email=params.email,
        remark=params.remark,
        sort=params.sort,
        status=params.status
    )
    if department:
        return Response.success(msg="添加成功！")
    else:
        return Response.error(msg="添加失败！")


@departmentAPI.delete("/delete/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="删除部门")
@departmentAPI.post("/delete/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="删除部门")
@Log(title="删除部门", business_type=BusinessType.DELETE)
async def delete_department(request: Request, id: str = Path(description="部门ID")):
    if department := await Department.get_or_none(id=id, del_flag=1):
        if await delete_department_recursive(department_id=department.id):
            return Response.success(msg="删除成功！")
        return Response.error(msg="删除失败!")
    else:
        return Response.error(msg="删除失败,部门不存在！")


@departmentAPI.delete("/deleteList", response_model=BaseResponse, response_class=JSONResponse, summary="批量删除部门")
@departmentAPI.post("/deleteList", response_model=BaseResponse, response_class=JSONResponse, summary="批量删除部门")
@Log(title="批量删除部门", business_type=BusinessType.DELETE)
async def delete_department_list(request: Request, params: DeleteDepartmentListParams):
    for item in set(params.ids):
        if department := await Department.get_or_none(id=item, del_flag=1):
            await delete_department_recursive(department_id=department.id)
    return Response.success(msg="删除成功！")


async def delete_department_recursive(department_id: str):
    """
    递归删除部门及其附属部门
    :param department_id: 部门ID
    :return:
    """
    await Department.filter(id=department_id).delete()
    sub_departments = await Department.filter(parent_id=department_id).all()
    for sub_department in sub_departments:
        await delete_department_recursive(sub_department.id)
    return True


@departmentAPI.put("/update/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="修改部门")
@departmentAPI.post("/update/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="修改部门")
@Log(title="修改部门", business_type=BusinessType.UPDATE)
async def update_department(request: Request, params: AddDepartmentParams, id: str = Path(description="部门ID")):
    if department := await Department.get_or_none(id=id, del_flag=1):
        department.name = params.name
        department.parent_id = params.parent_id
        department.principal = params.principal
        department.phone = params.phone
        department.email = params.email
        department.remark = params.remark
        department.sort = params.sort
        department.status = params.status
        await department.save()
        return Response.success(msg="修改成功！")
    else:
        return Response.error(msg="修改失败,部门不存在！")


@departmentAPI.get("/info/{id}", response_model=GetDepartmentInfoResponse, response_class=JSONResponse,
                   summary="查询部门详情")
@Log(title="查询部门详情", business_type=BusinessType.SELECT)
async def get_department(request: Request, id: str = Path(description="部门ID")):
    if department := await Department.get_or_none(id=id, del_flag=1).values(
            id="id",
            name="name",
            parent_id="parent_id",
            principal="principal",
            phone="phone",
            email="email",
            remark="remark",
            sort="sort",
            status="status",
            create_time="create_time",
            update_time="update_time",
            create_by="create_by",
            update_by="update_by"
    ):
        return Response.success(data=department)
    else:
        return Response.error(msg="部门不存在！")


@departmentAPI.get("/list", response_model=GetDepartmentListResponse, response_class=JSONResponse,
                   summary="查询部门列表")
@Log(title="查询部门列表", business_type=BusinessType.SELECT)
async def get_department_list(
        request: Request,
        page: int = Query(default=1, description="当前页码"),
        pageSize: int = Query(default=10, description="每页条数"),
        name: Optional[str] = Query(default=None, description="部门名称"),
        principal: Optional[str] = Query(default=None, description="负责人"),
        phone: Optional[str] = Query(default=None, description="电话"),
        email: Optional[str] = Query(default=None, description="邮箱"),
        remark: Optional[str] = Query(default=None, description="备注"),
        sort: Optional[int] = Query(default=None, description="排序权重"),
        current_user: dict = Depends(LoginController.get_current_user)
):
    filterArgs = {
        f'{k}__contains': v for k, v in {
            'name': name,
            'principal': principal,
            'phone': phone,
            'email': email,
            'remark': remark,
            'sort': sort
        }.items() if v
    }
    department_id = current_user.get("department_id", "")
    # 递归查询所有部门
    all_departments = await get_department_and_subdepartments(department_id, filterArgs)

    # 分页处理
    total = len(all_departments)
    paginated_departments = all_departments[(page - 1) * pageSize: page * pageSize]
    return Response.success(data={
        "result": paginated_departments,
        "total": total,
        "page": page
    })


async def get_department_and_subdepartments(department_id: str, filterArgs: dict, visited: set = None):
    """
    查询当前部门及其所有下属部门的数据，并根据 id 去重。

    :param department_id: 当前部门 ID
    :param filterArgs: 过滤条件
    :param visited: 已访问的部门 ID 集合，用于避免循环依赖
    :return: 去重后的部门列表
    """
    if visited is None:
        visited = set()  # 初始化已访问的部门 ID 集合

    # 如果当前部门 ID 已经访问过，直接返回空列表，避免死循环
    if department_id in visited:
        return []

    visited.add(department_id)  # 标记当前部门 ID 为已访问

    # 查询当前部门
    current_department = await Department.filter(
        id=department_id,
        **filterArgs
    ).values(
        id="id",
        name="name",
        parent_id="parent_id",
        principal="principal",
        phone="phone",
        email="email",
        remark="remark",
        sort="sort",
        status="status",
        create_time="create_time",
        update_time="update_time",
        create_by="create_by",
        update_by="update_by"
    )

    # 查询直接子部门
    sub_departments = await Department.filter(
        parent_id=department_id,  # 只根据 parent_id 查询
        **filterArgs
    ).values(
        id="id",
        name="name",
        parent_id="parent_id",
        principal="principal",
        phone="phone",
        email="email",
        remark="remark",
        sort="sort",
        status="status",
        create_time="create_time",
        update_time="update_time",
        create_by="create_by",
        update_by="update_by"
    )

    # 递归查询子部门的子部门
    for department in sub_departments[:]:  # 使用切片复制避免修改迭代中的列表
        sub_sub_departments = await get_department_and_subdepartments(department["id"], filterArgs, visited)
        sub_departments.extend(sub_sub_departments)

    # 合并当前部门和所有下属部门的数据
    all_departments = current_department + sub_departments

    # 根据 id 去重
    unique_departments = []
    seen_ids = set()  # 用于记录已经处理过的部门 ID
    for department in all_departments:
        if department["id"] not in seen_ids:
            unique_departments.append(department)
            seen_ids.add(department["id"])

    return unique_departments


@departmentAPI.post("/addRole", response_model=BaseResponse, response_class=JSONResponse, summary="添加部门角色")
@Log(title="添加部门角色", business_type=BusinessType.INSERT)
async def add_department_role(request: Request, params: AddDepartmentRoleParams):
    if await DepartmentRole.get_or_none(department_id=params.department_id, role_id=params.role_id, del_flag=1):
        return Response.error(msg="该部门已存在该角色！")
    if department := await Department.get_or_none(id=params.department_id, del_flag=1):
        if role := await Role.get_or_none(id=params.role_id, del_flag=1):
            departmentRole = await DepartmentRole.create(department_id=department.id, role_id=role.id)
            if departmentRole:
                return Response.success(msg="添加成功！")
            else:
                return Response.error(msg="添加失败！")
        else:
            return Response.error(msg="添加失败,角色不存在！")
    else:
        return Response.error(msg="添加失败,部门不存在！")


@departmentAPI.delete("/deleteRole/{id}", response_model=BaseResponse, response_class=JSONResponse,
                      summary="删除部门角色")
@departmentAPI.post("/deleteRole/{id}", response_model=BaseResponse, response_class=JSONResponse,
                    summary="删除部门角色")
@Log(title="删除部门角色", business_type=BusinessType.DELETE)
async def delete_department_role(request: Request, id: str = Path(description="部门角色ID")):
    if departmentRole := await DepartmentRole.get_or_none(id=id, del_flag=1):
        await departmentRole.delete()
        return Response.success(msg="删除成功！")
    else:
        return Response.error(msg="删除失败,部门角色不存在！")


@departmentAPI.put("/updateRole/{id}", response_model=BaseResponse, response_class=JSONResponse, summary="修改部门角色")
@departmentAPI.post("/updateRole/{id}", response_model=BaseResponse, response_class=JSONResponse,
                    summary="修改部门角色")
@Log(title="修改部门角色", business_type=BusinessType.UPDATE)
async def update_department_role(request: Request, params: AddDepartmentRoleParams,
                                 id: str = Path(description="部门角色ID")):
    if departmentRole := await DepartmentRole.get_or_none(id=id, del_flag=1):
        if department := await Department.get_or_none(id=params.department_id, del_flag=1):
            if role := await Role.get_or_none(id=params.role_id, del_flag=1):
                departmentRole.department_id = department.id
                departmentRole.role_id = role.id
                await departmentRole.save()
                return Response.success(msg="修改成功！")
            else:
                return Response.error(msg="修改失败,角色不存在！")
        else:
            return Response.error(msg="修改失败,部门不存在！")
    else:
        return Response.error(msg="修改失败,部门角色不存在！")


@departmentAPI.get("/roleInfo", response_model=GetDepartmentRoleInfoResponse, response_class=JSONResponse,
                   summary="获取部门角色信息")
@Log(title="获取部门角色信息", business_type=BusinessType.SELECT)
async def get_department_role_info(request: Request, id: str = Query(description="部门角色ID")):
    if departmentRole := await DepartmentRole.get_or_none(id=id, del_flag=1):
        data = await departmentRole.first().values(
            id="id",
            department_id="department__id",
            department_name="department__name",
            department_phone="department__phone",
            department_principal="department__principal",
            department_email="department__email",
            role_name="role__name",
            role_code="role__code",
            role_id="role__id",
            create_time="create_time",
            update_time="update_time"
        )
        return Response.success(data=data)
    else:
        return Response.error(msg="获取失败,部门角色不存在！")


@departmentAPI.get("/roleList", response_model=GetDepartmentListResponse, response_class=JSONResponse,
                   summary="获取部门角色列表")
@Log(title="获取部门角色列表", business_type=BusinessType.SELECT)
async def get_department_role_list(
        request: Request,
        page: int = Query(default=1, description="当前页码"),
        pageSize: int = Query(default=10, description="每页条数"),
        department_id: Optional[str] = Query(default=None, description="部门ID"),
        department_name: Optional[str] = Query(default=None, description="部门名称"),
        department_phone: Optional[str] = Query(default=None, description="部门电话"),
        department_principal: Optional[str] = Query(default=None, description="部门负责人"),
        department_email: Optional[str] = Query(default=None, description="部门邮箱"),
        role_id: Optional[str] = Query(default=None, description="角色ID"),
        role_name: Optional[str] = Query(default=None, description="角色名称"),
        role_code: Optional[str] = Query(default=None, description="角色编码"),
):
    filterArgs = {
        f'{k}__contains': v for k, v in {
            'department__id': department_id,
            'department__name': department_name,
            'department__phone': department_phone,
            'department__principal': department_principal,
            'department__email': department_email,
            'role__id': role_id,
            'role__name': role_name,
            'role__code': role_code
        }.items() if v
    }
    total = await DepartmentRole.filter(**filterArgs).count()
    data = await DepartmentRole.filter(**filterArgs).offset((page - 1) * pageSize).limit(pageSize).values(
        id="id",
        department_id="department__id",
        department_name="department__name",
        department_phone="department__phone",
        department_principal="department__principal",
        department_email="department__email",
        role_name="role__name",
        role_code="role__code",
        role_id="role__id",
        create_time="create_time",
        update_time="update_time"
    )
    return Response.success(data={
        "result": data,
        "total": total,
        "page": page
    })


@departmentAPI.get("/roleList/{id}", response_model=GetDepartmentListResponse, response_class=JSONResponse,
                   summary="用户获取部门角色列表")
@Log(title="获取部门角色列表", business_type=BusinessType.OTHER)
async def get_department_role_list(
        request: Request,
        id: str = Path(..., description="部门ID")
):
    data = await Role.filter(department__id=id).values(
        id="id",
        department_id="department__id",
        department_name="department__name",
        department_phone="department__phone",
        department_principal="department__principal",
        department_email="department__email",
        role_name="name",
        role_code="code",
        role_id="id",
        create_time="create_time",
        update_time="update_time"
    )
    return Response.success(data={
        "result": data,
        "total": len(data),
        "page": 1
    })
