from __future__ import annotations

from typing import Any

from fastapi import APIRouter, Depends, HTTPException, Query

from app.modules.auth.presentation.auth import get_current_user, require_role
from app.models.schemas import (
    DossierReviewFindingCreateRequest,
    DossierReviewSessionCreateRequest,
    DossierReviewSessionRecord,
    DossierReviewSessionsResponse,
    WorkflowReviewAssignmentRequest,
    WorkflowReviewCloseRequest,
    WorkflowReviewRunSummary,
    WorkflowReviewStartRequest,
    WorkflowReviewSubmissionRequest,
    WorkflowReviewVerificationRequest,
)

from .helpers import (
    _build_postgres_client,
    _build_workflow_persistence_service,
    _get_review_or_404,
)

router = APIRouter()


@router.post("/v1/dossiers/reviews", response_model=DossierReviewSessionRecord)
def create_dossier_review(
    payload: DossierReviewSessionCreateRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm", "site_engineer"])
    ),
) -> DossierReviewSessionRecord:
    """Create a dossier review session in PostgreSQL."""
    postgres_client = _build_postgres_client()
    try:
        session = postgres_client.create_dossier_review_session(
            payload.model_dump(exclude_none=True)
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return DossierReviewSessionRecord(**session)


@router.get("/v1/dossiers/reviews", response_model=DossierReviewSessionsResponse)
def list_dossier_reviews(
    project_code: str | None = Query(default=None),
    status: str | None = Query(default=None),
    current_user: dict[str, Any] = Depends(get_current_user),
) -> DossierReviewSessionsResponse:
    """List dossier review sessions from PostgreSQL."""
    postgres_client = _build_postgres_client()
    items = postgres_client.fetch_dossier_review_sessions(project_code=project_code)
    if status:
        items = [
            item
            for item in items
            if str(item.get("status", "")).strip().lower() == status.strip().lower()
        ]
    return DossierReviewSessionsResponse(
        items=[DossierReviewSessionRecord(**item) for item in items],
        source="postgres",
        used_fallback=False,
        message="Dossier review workflow đang dùng PostgreSQL làm nguồn dữ liệu chính.",
    )


@router.get(
    "/v1/dossiers/reviews/{review_id}", response_model=DossierReviewSessionRecord
)
def get_dossier_review(
    review_id: str, current_user: dict[str, Any] = Depends(get_current_user)
) -> DossierReviewSessionRecord:
    """Return one dossier review session by its review_id."""
    return _get_review_or_404(_build_postgres_client(), review_id)


@router.post(
    "/v1/dossiers/reviews/{review_id}/findings",
    response_model=DossierReviewSessionRecord,
)
def add_dossier_review_finding(
    review_id: str,
    payload: DossierReviewFindingCreateRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm", "site_engineer"])
    ),
) -> DossierReviewSessionRecord:
    """Create a finding in PostgreSQL and return the refreshed review session."""
    postgres_client = _build_postgres_client()
    try:
        postgres_client.create_dossier_review_finding(
            review_id, payload.model_dump(exclude_none=True)
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return _get_review_or_404(postgres_client, review_id)


@router.post(
    "/v1/dossiers/reviews/{review_id}/findings/{finding_id}/assignments",
    response_model=DossierReviewSessionRecord,
)
def assign_dossier_review_finding(
    review_id: str,
    finding_id: str,
    payload: WorkflowReviewAssignmentRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm"])
    ),
) -> DossierReviewSessionRecord:
    """Assign a finding in PostgreSQL and return the refreshed review session."""
    postgres_client = _build_postgres_client()
    try:
        postgres_client.assign_dossier_review_finding(
            review_id, finding_id, payload.model_dump(exclude_none=True)
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return _get_review_or_404(postgres_client, review_id)


@router.post(
    "/v1/dossiers/reviews/{review_id}/findings/{finding_id}/assignments/{assignment_id}/submissions",
    response_model=DossierReviewSessionRecord,
)
def submit_dossier_review_supplement(
    review_id: str,
    finding_id: str,
    assignment_id: str,
    payload: WorkflowReviewSubmissionRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm", "site_engineer"])
    ),
) -> DossierReviewSessionRecord:
    """Submit supplement data in PostgreSQL and return the refreshed review session."""
    postgres_client = _build_postgres_client()
    try:
        submission_payload = payload.model_dump(exclude_none=True)
        submission_payload["assignment_id"] = assignment_id
        postgres_client.submit_dossier_review_supplement(
            review_id, finding_id, submission_payload
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return _get_review_or_404(postgres_client, review_id)


@router.post(
    "/v1/dossiers/reviews/{review_id}/findings/{finding_id}/assignments/{assignment_id}/verify",
    response_model=DossierReviewSessionRecord,
)
def verify_dossier_review_finding(
    review_id: str,
    finding_id: str,
    assignment_id: str,
    payload: WorkflowReviewVerificationRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm"])
    ),
) -> DossierReviewSessionRecord:
    """Verify a finding in PostgreSQL and return the refreshed review session."""
    postgres_client = _build_postgres_client()
    try:
        verify_payload = payload.model_dump(exclude_none=True)
        verify_payload["assignment_id"] = assignment_id
        postgres_client.verify_dossier_review_finding(
            review_id, finding_id, verify_payload
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return _get_review_or_404(postgres_client, review_id)


@router.post(
    "/v1/dossiers/reviews/{review_id}/close", response_model=DossierReviewSessionRecord
)
def close_dossier_review(
    review_id: str,
    payload: WorkflowReviewCloseRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm"])
    ),
) -> DossierReviewSessionRecord:
    """Close a dossier review session in PostgreSQL."""
    postgres_client = _build_postgres_client()
    try:
        session = postgres_client.close_dossier_review_session(
            review_id, payload.model_dump(exclude_none=True)
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return DossierReviewSessionRecord(**session)


@router.post(
    "/v1/workflows/dossier-review/start", response_model=WorkflowReviewRunSummary
)
def start_dossier_review_workflow(
    payload: WorkflowReviewStartRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm", "site_engineer"])
    ),
) -> WorkflowReviewRunSummary:
    """Start a persisted dossier review workflow run and return its structured summary."""
    service = _build_workflow_persistence_service()
    try:
        return service.start_review_run(payload)
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
