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

from app.api.deps import require_roles
from app.db.session import get_db
from app.models import AdminUser, ProjectCourse
from app.schemas.project import ProjectCourseCreate, ProjectCourseOut, ProjectCourseUpdate
from app.services.logs import diff_values, log_action
from app.services.certificate_templates import get_certificate_template

router = APIRouter()


@router.get("", response_model=list[ProjectCourseOut])
def list_projects(
    db: Session = Depends(get_db),
    _: AdminUser = Depends(require_roles("system_admin", "certificate_admin", "readonly")),
) -> list[ProjectCourse]:
    return db.query(ProjectCourse).order_by(ProjectCourse.code.asc()).all()


@router.post("", response_model=ProjectCourseOut, status_code=status.HTTP_201_CREATED)
def create_project(
    payload: ProjectCourseCreate,
    db: Session = Depends(get_db),
    admin: AdminUser = Depends(require_roles("system_admin", "certificate_admin")),
) -> ProjectCourse:
    try:
        template_code = get_certificate_template(payload.default_template_code).code
    except (ValueError, FileNotFoundError) as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
    if db.query(ProjectCourse).filter(ProjectCourse.code == payload.code).first():
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="项目代码已存在")
    project = ProjectCourse(
        code=payload.code,
        name=payload.name,
        default_certificate_name=payload.name,
        default_course_name=payload.default_course_name,
        default_stage_name=payload.default_stage_name,
        default_template_code=template_code,
    )
    db.add(project)
    log_action(db, admin, "create_project", "project_course", detail={"code": payload.code, "name": payload.name, "status": project.status})
    db.commit()
    db.refresh(project)
    return project


@router.put("/{project_id}", response_model=ProjectCourseOut)
def update_project(
    project_id: int,
    payload: ProjectCourseUpdate,
    db: Session = Depends(get_db),
    admin: AdminUser = Depends(require_roles("system_admin", "certificate_admin")),
) -> ProjectCourse:
    project = db.get(ProjectCourse, project_id)
    if not project:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="项目不存在")
    before = {
        "name": project.name,
        "default_course_name": project.default_course_name,
        "default_stage_name": project.default_stage_name,
        "default_template_code": project.default_template_code,
        "status": project.status,
    }
    if payload.name is not None:
        project.name = payload.name
        project.default_certificate_name = payload.name
    if payload.default_course_name is not None:
        project.default_course_name = payload.default_course_name
    if payload.default_stage_name is not None:
        project.default_stage_name = payload.default_stage_name
    if payload.default_template_code is not None:
        try:
            template_code = get_certificate_template(payload.default_template_code).code
        except (ValueError, FileNotFoundError) as exc:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
        project.default_template_code = template_code
    if payload.status is not None:
        project.status = payload.status
    after = {
        "name": project.name,
        "default_course_name": project.default_course_name,
        "default_stage_name": project.default_stage_name,
        "default_template_code": project.default_template_code,
        "status": project.status,
    }
    log_action(db, admin, "update_project", "project_course", project.id, {"code": project.code, "name": project.name, "changes": diff_values(before, after, list(after.keys()))})
    db.commit()
    db.refresh(project)
    return project
