from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from app.db.session import get_db
from app.schemas.system_permissions import (
    EmployeeOption,
    MenuPermissionNode,
    OrgEmployeeBind,
    OrgNodeCreate,
    OrgNodeRead,
    OrgNodeUpdate,
    PermissionRead,
    RoleCreate,
    RolePermissionUpdate,
    RoleRead,
    RoleUpdate,
    SystemUserCreate,
    SystemUserPasswordReset,
    SystemUserRead,
    SystemUserRoleUpdate,
    SystemUserStatusUpdate,
)
from app.services.auth import AuthContext, require_system_admin
from app.services.system_permissions import (
    build_org_tree,
    bind_org_employee,
    create_org_node,
    create_role,
    create_system_user,
    delete_org_node,
    list_employee_options,
    list_menu_permission_tree,
    list_permissions,
    list_roles,
    list_system_users,
    reset_system_user_password,
    unbind_org_employee,
    update_org_node,
    update_role,
    update_system_user_roles,
    update_system_user_status,
)

router = APIRouter(dependencies=[Depends(require_system_admin)])


@router.get("/org-tree", response_model=list[OrgNodeRead])
def get_org_tree(db: Session = Depends(get_db)) -> list[OrgNodeRead]:
    return build_org_tree(db)


@router.post("/org-nodes", response_model=OrgNodeRead)
def post_org_node(payload: OrgNodeCreate, db: Session = Depends(get_db)) -> OrgNodeRead:
    return create_org_node(db, payload)


@router.put("/org-nodes/{node_id}", response_model=OrgNodeRead)
def put_org_node(node_id: int, payload: OrgNodeUpdate, db: Session = Depends(get_db)) -> OrgNodeRead:
    return update_org_node(db, node_id, payload)


@router.delete("/org-nodes/{node_id}", status_code=204)
def delete_org_node_route(node_id: int, db: Session = Depends(get_db)) -> None:
    delete_org_node(db, node_id)


@router.post("/org-nodes/{node_id}/employees", response_model=OrgNodeRead)
def post_org_node_employee(
    node_id: int,
    payload: OrgEmployeeBind,
    db: Session = Depends(get_db),
) -> OrgNodeRead:
    return bind_org_employee(db, node_id, payload)


@router.delete("/org-nodes/{node_id}/employees/{employee_id}", response_model=OrgNodeRead)
def delete_org_node_employee(
    node_id: int,
    employee_id: int,
    db: Session = Depends(get_db),
) -> OrgNodeRead:
    return unbind_org_employee(db, node_id, employee_id)


@router.get("/permissions", response_model=list[PermissionRead])
def get_permissions(db: Session = Depends(get_db)) -> list[PermissionRead]:
    return list_permissions(db)


@router.get("/menu-permission-tree", response_model=list[MenuPermissionNode])
def get_menu_permission_tree() -> list[MenuPermissionNode]:
    return list_menu_permission_tree()


@router.get("/roles", response_model=list[RoleRead])
def get_roles(db: Session = Depends(get_db)) -> list[RoleRead]:
    return list_roles(db)


@router.post("/roles", response_model=RoleRead)
def post_role(payload: RoleCreate, db: Session = Depends(get_db)) -> RoleRead:
    return create_role(db, payload)


@router.put("/roles/{role_id}", response_model=RoleRead)
def put_role(role_id: int, payload: RoleUpdate, db: Session = Depends(get_db)) -> RoleRead:
    return update_role(db, role_id, payload)


@router.put("/roles/{role_id}/permissions", response_model=RoleRead)
def put_role_permissions(
    role_id: int,
    payload: RolePermissionUpdate,
    db: Session = Depends(get_db),
) -> RoleRead:
    existing_role = next((role for role in list_roles(db) if role.role_id == role_id), None)
    if not existing_role:
        raise HTTPException(status_code=404, detail="角色不存在")
    return update_role(
        db,
        role_id,
        RoleUpdate(
            role_name=existing_role.role_name,
            role_scope=existing_role.role_scope,
            status=existing_role.status,
            remark=existing_role.remark,
            permission_codes=payload.permission_codes,
        ),
    )


@router.get("/employee-options", response_model=list[EmployeeOption])
def get_employee_options(
    limit: int = Query(default=500, ge=1, le=500),
    db: Session = Depends(get_db),
) -> list[EmployeeOption]:
    return list_employee_options(db, limit=limit)


@router.get("/users", response_model=list[SystemUserRead])
def get_system_users(db: Session = Depends(get_db)) -> list[SystemUserRead]:
    return list_system_users(db)


@router.post("/users", response_model=SystemUserRead)
def post_system_user(payload: SystemUserCreate, db: Session = Depends(get_db)) -> SystemUserRead:
    return create_system_user(db, payload)


@router.put("/users/{user_id}/roles", response_model=SystemUserRead)
def put_system_user_roles(
    user_id: int,
    payload: SystemUserRoleUpdate,
    db: Session = Depends(get_db),
) -> SystemUserRead:
    return update_system_user_roles(db, user_id, payload.role_ids)


@router.put("/users/{user_id}/status", response_model=SystemUserRead)
def put_system_user_status(
    user_id: int,
    payload: SystemUserStatusUpdate,
    db: Session = Depends(get_db),
    context: AuthContext = Depends(require_system_admin),
) -> SystemUserRead:
    return update_system_user_status(db, user_id, payload.status, context.user.id)


@router.post("/users/{user_id}/reset-password", response_model=SystemUserRead)
def post_system_user_password_reset(
    user_id: int,
    payload: SystemUserPasswordReset,
    db: Session = Depends(get_db),
) -> SystemUserRead:
    return reset_system_user_password(db, user_id, payload.password)
