from __future__ import annotations

from typing import Annotated

from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile, status
from fastapi.responses import Response
from sqlalchemy.orm import Session

from app.api.deps import CurrentUserContext, get_db, require_admin_user
from app.api.pagination import PageNumber, PageSize, page_payload, wants_page
from app.schemas.common import ErrorResponse, PaginatedResponse
from app.schemas.employee import (
    EmployeeCreate,
    EmployeeImportResultRead,
    EmployeeMetaRead,
    EmployeeRead,
    EmployeeUpdate,
)
from app.services.employee import EmployeeService
from app.services.employee_pagination import EmployeePaginationService

router = APIRouter(dependencies=[Depends(require_admin_user)])
DbSession = Annotated[Session, Depends(get_db)]
AdminUser = Annotated[CurrentUserContext, Depends(require_admin_user)]


def _employee_service(db: Session, current_user: CurrentUserContext) -> EmployeeService:
    return EmployeeService(db, tenant_id=current_user.tenant_id)


@router.get(
    "/meta",
    response_model=EmployeeMetaRead,
    summary="读取员工目录元数据",
    description="返回员工总数、状态汇总和可选角色列表，供员工管理页面初始化使用。",
)
def get_employee_meta(db: DbSession, current_user: AdminUser) -> EmployeeMetaRead:
    return _employee_service(db, current_user).get_employee_meta()


@router.get(
    "",
    response_model=list[EmployeeRead] | PaginatedResponse[EmployeeRead],
    summary="查询员工列表",
    description="按状态和关键字筛选员工目录。",
)
def list_employees(
    db: DbSession,
    current_user: AdminUser,
    status_filter: Annotated[
        str | None,
        Query(alias="status", description="员工状态筛选值。"),
    ] = None,
    keyword: Annotated[
        str | None,
        Query(description="姓名、工号、邮箱等关键字模糊查询。"),
    ] = None,
    page: PageNumber = None,
    page_size: PageSize = None,
) -> list[EmployeeRead] | PaginatedResponse[EmployeeRead]:
    if wants_page(page, page_size):
        return page_payload(
            EmployeePaginationService(
                db,
                tenant_id=current_user.tenant_id,
            ).list_employees_page(
                status=status_filter,
                keyword=keyword,
                page=page,
                page_size=page_size,
            )
        )
    return _employee_service(db, current_user).list_employees(
        status=status_filter,
        keyword=keyword,
    )


@router.get(
    "/import-template",
    summary="下载员工导入模板",
    description="下载固定格式的员工 Excel 导入模板。",
)
def download_employee_import_template(db: DbSession, current_user: AdminUser) -> Response:
    content = _employee_service(db, current_user).build_import_template()
    return Response(
        content=content,
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={
            "Content-Disposition": 'attachment; filename="employee-import-template.xlsx"'
        },
    )


@router.get(
    "/export",
    summary="导出员工 Excel",
    description="按筛选条件导出员工目录 Excel 文件。",
)
def export_employees(
    db: DbSession,
    current_user: AdminUser,
    status_filter: Annotated[
        str | None,
        Query(alias="status", description="员工状态筛选值。"),
    ] = None,
    keyword: Annotated[
        str | None,
        Query(description="姓名、工号、邮箱等关键字模糊查询。"),
    ] = None,
) -> Response:
    content = _employee_service(db, current_user).export_employees(
        status=status_filter,
        keyword=keyword,
    )
    return Response(
        content=content,
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": 'attachment; filename="employee-export.xlsx"'},
    )


@router.post(
    "/import",
    response_model=EmployeeImportResultRead,
    summary="导入员工 Excel",
    description="按模板批量导入员工。全部校验通过后才写入数据库，任一行有错则整批不导入。",
)
async def import_employees(
    db: DbSession,
    current_user: AdminUser,
    file: Annotated[UploadFile, File(description="待导入的员工 Excel 文件。")],
) -> EmployeeImportResultRead:
    filename = (file.filename or "").lower()
    if not filename.endswith(".xlsx"):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="当前仅支持上传 .xlsx 格式的员工表格。",
        )

    content = await file.read()
    return _employee_service(db, current_user).import_employees(
        content,
        actor=current_user.username,
    )


@router.post(
    "",
    response_model=EmployeeRead,
    status_code=status.HTTP_201_CREATED,
    summary="创建员工",
    description="创建新的员工目录记录，并初始化基础角色与组织归属。",
    responses={
        status.HTTP_400_BAD_REQUEST: {
            "model": ErrorResponse,
            "description": "员工数据校验失败。",
        }
    },
)
def create_employee(
    payload: EmployeeCreate,
    db: DbSession,
    current_user: AdminUser,
) -> EmployeeRead:
    try:
        return _employee_service(db, current_user).create_employee(payload)
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc


@router.get(
    "/{employee_id}",
    response_model=EmployeeRead,
    summary="读取员工详情",
    description="根据员工主键读取员工完整档案信息。",
    responses={
        status.HTTP_404_NOT_FOUND: {
            "model": ErrorResponse,
            "description": "员工不存在。",
        }
    },
)
def get_employee(
    employee_id: str,
    db: DbSession,
    current_user: AdminUser,
) -> EmployeeRead:
    employee = _employee_service(db, current_user).get_employee(employee_id)
    if employee is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Employee not found")
    return employee


@router.patch(
    "/{employee_id}",
    response_model=EmployeeRead,
    summary="更新员工",
    description="更新员工基础信息、角色、密码等可维护字段。",
    responses={
        status.HTTP_400_BAD_REQUEST: {
            "model": ErrorResponse,
            "description": "请求字段不合法。",
        },
        status.HTTP_404_NOT_FOUND: {
            "model": ErrorResponse,
            "description": "员工不存在。",
        },
    },
)
def update_employee(
    employee_id: str,
    payload: EmployeeUpdate,
    db: DbSession,
    current_user: AdminUser,
) -> EmployeeRead:
    try:
        return _employee_service(db, current_user).update_employee(employee_id, payload)
    except LookupError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc


@router.post(
    "/{employee_id}/disable",
    response_model=EmployeeRead,
    summary="停用员工",
    description="将员工状态切换为停用，阻止其继续登录系统。",
    responses={
        status.HTTP_404_NOT_FOUND: {
            "model": ErrorResponse,
            "description": "员工不存在。",
        }
    },
)
def disable_employee(
    employee_id: str,
    db: DbSession,
    current_user: AdminUser,
) -> EmployeeRead:
    try:
        return _employee_service(db, current_user).disable_employee(employee_id)
    except LookupError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc


@router.post(
    "/{employee_id}/enable",
    response_model=EmployeeRead,
    summary="启用员工",
    description="将停用员工恢复为在职状态，使其可以重新登录系统。",
    responses={
        status.HTTP_404_NOT_FOUND: {
            "model": ErrorResponse,
            "description": "员工不存在。",
        }
    },
)
def enable_employee(
    employee_id: str,
    db: DbSession,
    current_user: AdminUser,
) -> EmployeeRead:
    try:
        return _employee_service(db, current_user).enable_employee(employee_id)
    except LookupError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
