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

from app import models, schemas
from app.database import get_db
from app.services.standard_qa_service import add_audit_log, mark_standard_call_status

router = APIRouter(prefix="/standard-qa", tags=["standard_qa"])


def _get_standard(db: Session, standard_id: int) -> models.StandardQAItem:
    standard = db.get(models.StandardQAItem, standard_id)
    if not standard:
        raise HTTPException(status_code=404, detail="标准问答不存在")
    return standard


@router.get("/callable", response_model=list[schemas.CallableQARead])
def callable_qa(db: Session = Depends(get_db)) -> list[models.StandardQAItem]:
    return (
        db.query(models.StandardQAItem)
        .join(models.RawQAItem)
        .filter(
            models.StandardQAItem.audit_status == models.AuditStatus.approved,
            models.StandardQAItem.call_status == models.CallStatus.callable,
            models.StandardQAItem.risk_level.in_([models.RiskLevel.low, models.RiskLevel.medium]),
            models.RawQAItem.desensitization_status.in_(
                [models.DesensitizationStatus.not_needed, models.DesensitizationStatus.done]
            ),
        )
        .order_by(models.StandardQAItem.updated_at.desc())
        .all()
    )


@router.get("", response_model=list[schemas.StandardQARead])
def list_standard_qa(
    audit_status: str | None = None,
    call_status: str | None = None,
    risk_level: str | None = None,
    primary_topic: str | None = None,
    course_stage: str | None = None,
    db: Session = Depends(get_db),
) -> list[models.StandardQAItem]:
    query = db.query(models.StandardQAItem)
    if audit_status:
        query = query.filter(models.StandardQAItem.audit_status == audit_status)
    if call_status:
        query = query.filter(models.StandardQAItem.call_status == call_status)
    if risk_level:
        query = query.filter(models.StandardQAItem.risk_level == risk_level)
    if primary_topic:
        query = query.filter(models.StandardQAItem.primary_topic == primary_topic)
    if course_stage:
        query = query.filter(models.StandardQAItem.course_stage == course_stage)
    return query.order_by(models.StandardQAItem.updated_at.desc()).all()


@router.get("/{standard_id}", response_model=schemas.StandardQARead)
def get_standard_qa(standard_id: int, db: Session = Depends(get_db)) -> models.StandardQAItem:
    return _get_standard(db, standard_id)


@router.patch("/{standard_id}", response_model=schemas.StandardQARead)
def update_standard_qa(
    standard_id: int, payload: schemas.StandardQAUpdate, db: Session = Depends(get_db)
) -> models.StandardQAItem:
    standard = _get_standard(db, standard_id)
    for key, value in payload.model_dump(exclude_unset=True).items():
        setattr(standard, key, value)
    db.commit()
    db.refresh(standard)
    return standard


@router.post("/{standard_id}/mark-callable", response_model=schemas.StandardQARead)
def mark_callable(
    standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db)
) -> models.StandardQAItem:
    payload = payload or schemas.ReviewActionRequest()
    try:
        return mark_standard_call_status(
            db, _get_standard(db, standard_id), models.CallStatus.callable, payload.reviewer_id, payload.comment
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc


@router.post("/{standard_id}/mark-not-callable", response_model=schemas.StandardQARead)
def mark_not_callable(
    standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db)
) -> models.StandardQAItem:
    payload = payload or schemas.ReviewActionRequest()
    return mark_standard_call_status(
        db, _get_standard(db, standard_id), models.CallStatus.not_callable, payload.reviewer_id, payload.comment
    )


@router.post("/{standard_id}/disable", response_model=schemas.StandardQARead)
def disable_standard(
    standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db)
) -> models.StandardQAItem:
    payload = payload or schemas.ReviewActionRequest()
    standard = _get_standard(db, standard_id)
    before = standard.audit_status.value
    standard.audit_status = models.AuditStatus.disabled
    standard.call_status = models.CallStatus.forbidden
    standard.disabled_reason = payload.comment
    add_audit_log(
        db,
        user_id=payload.reviewer_id,
        target_type=models.TargetType.standard_qa,
        target_id=standard.id,
        action=models.AuditAction.disable,
        before_status=before,
        after_status=standard.audit_status.value,
        comment=payload.comment,
    )
    db.commit()
    db.refresh(standard)
    return standard


@router.post("/{standard_id}/need-review", response_model=schemas.StandardQARead)
def need_review(
    standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db)
) -> models.StandardQAItem:
    payload = payload or schemas.ReviewActionRequest()
    standard = _get_standard(db, standard_id)
    before = standard.audit_status.value
    standard.audit_status = models.AuditStatus.needs_revision
    standard.call_status = models.CallStatus.need_review
    add_audit_log(
        db,
        user_id=payload.reviewer_id,
        target_type=models.TargetType.standard_qa,
        target_id=standard.id,
        action=models.AuditAction.revise,
        before_status=before,
        after_status=standard.audit_status.value,
        comment=payload.comment,
    )
    db.commit()
    db.refresh(standard)
    return standard

