"""Per-language QC endpoints — assignment, approval, rejection, queue."""

from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from motor.motor_asyncio import AsyncIOMotorDatabase
from pydantic import BaseModel

from ...core.database import get_database
from ...core.dependencies import get_current_user, require_roles
from ...models.job import LanguageQCState, LanguageQCStatus
from ...models.user import User, UserRole
from ...services import language_qc as lqc

router = APIRouter(tags=["language-qc"])


# ── Request / response schemas ────────────────────────────────────────────────

class AssignRequest(BaseModel):
    linguist_user_id: str
    notes: Optional[str] = None


class ReassignRequest(BaseModel):
    linguist_user_id: str
    notes: Optional[str] = None


class ApproveLanguageRequest(BaseModel):
    notes: Optional[str] = None


class RejectLanguageRequest(BaseModel):
    notes: str


class ReopenLanguageRequest(BaseModel):
    notes: Optional[str] = None


class LanguageQCStateResponse(BaseModel):
    lang: str
    state: LanguageQCState


class LanguageQCMapResponse(BaseModel):
    job_id: str
    language_qc: dict[str, LanguageQCState]


class QueueItem(BaseModel):
    job_id: str
    job_title: str
    job_status: str
    lang: str
    lang_qc_status: str
    assigned_at: Optional[str] = None
    reviewed_at: Optional[str] = None


class QueueResponse(BaseModel):
    items: list[QueueItem]
    total: int


# ── Routes ────────────────────────────────────────────────────────────────────

@router.get("/jobs/{job_id}/language-qc", response_model=LanguageQCMapResponse)
async def get_language_qc(
    job_id: str,
    current_user: User = Depends(require_roles(
        UserRole.REVIEWER, UserRole.LINGUIST, UserRole.PRODUCTION,
        UserRole.PROJECT_MANAGER, UserRole.ADMIN,
    )),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Return per-language QC state map for a job."""
    states = await lqc.get_all_states(db, job_id)
    return LanguageQCMapResponse(job_id=job_id, language_qc=states)


@router.post("/jobs/{job_id}/languages/{lang}/assign", response_model=LanguageQCStateResponse)
async def assign_language(
    job_id: str,
    lang: str,
    request: AssignRequest,
    http_request: Request,
    current_user: User = Depends(require_roles(
        UserRole.PROJECT_MANAGER, UserRole.PRODUCTION, UserRole.ADMIN,
    )),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Assign a linguist to a language on this job (PM / PROD / ADMIN only)."""
    state = await lqc.assign_linguist(
        db, job_id, lang, request.linguist_user_id, current_user,
        http_request=http_request, notes=request.notes,
    )
    return LanguageQCStateResponse(lang=lang, state=state)


@router.post("/jobs/{job_id}/languages/{lang}/reassign", response_model=LanguageQCStateResponse)
async def reassign_language(
    job_id: str,
    lang: str,
    request: ReassignRequest,
    http_request: Request,
    current_user: User = Depends(require_roles(
        UserRole.LINGUIST, UserRole.PROJECT_MANAGER, UserRole.PRODUCTION, UserRole.ADMIN,
    )),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Hand off a language to another linguist (assigned linguist or PM/PROD/ADMIN)."""
    state = await lqc.reassign_linguist(
        db, job_id, lang, request.linguist_user_id, current_user,
        http_request=http_request, notes=request.notes,
    )
    return LanguageQCStateResponse(lang=lang, state=state)


@router.post("/jobs/{job_id}/languages/{lang}/approve", response_model=LanguageQCStateResponse)
async def approve_language(
    job_id: str,
    lang: str,
    request: ApproveLanguageRequest,
    http_request: Request,
    current_user: User = Depends(require_roles(
        UserRole.LINGUIST, UserRole.REVIEWER, UserRole.PRODUCTION, UserRole.ADMIN,
    )),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Approve a language (assigned linguist, PROD, or ADMIN)."""
    state = await lqc.approve_language(
        db, job_id, lang, current_user, http_request=http_request, notes=request.notes,
    )
    return LanguageQCStateResponse(lang=lang, state=state)


@router.post("/jobs/{job_id}/languages/{lang}/reject", response_model=LanguageQCStateResponse)
async def reject_language(
    job_id: str,
    lang: str,
    request: RejectLanguageRequest,
    http_request: Request,
    current_user: User = Depends(require_roles(
        UserRole.LINGUIST, UserRole.REVIEWER, UserRole.PRODUCTION, UserRole.ADMIN,
    )),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Reject a language with required notes (assigned linguist, PROD, or ADMIN)."""
    state = await lqc.reject_language(
        db, job_id, lang, current_user, request.notes, http_request=http_request,
    )
    return LanguageQCStateResponse(lang=lang, state=state)


@router.post("/jobs/{job_id}/languages/{lang}/reopen", response_model=LanguageQCStateResponse)
async def reopen_language(
    job_id: str,
    lang: str,
    request: ReopenLanguageRequest,
    http_request: Request,
    current_user: User = Depends(require_roles(UserRole.PRODUCTION, UserRole.ADMIN)),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Re-open an approved language for re-review (PROD / ADMIN only)."""
    state = await lqc.reopen_language(
        db, job_id, lang, current_user, http_request=http_request, notes=request.notes,
    )
    return LanguageQCStateResponse(lang=lang, state=state)


@router.get("/me/language-qc-queue", response_model=QueueResponse)
async def my_language_qc_queue(
    qc_status: Optional[str] = Query(None, description="Filter by status: pending, in_review, approved, rejected"),
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    current_user: User = Depends(require_roles(
        UserRole.LINGUIST, UserRole.REVIEWER, UserRole.PRODUCTION, UserRole.ADMIN,
    )),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """List jobs and languages assigned to the current user."""
    jobs = await lqc.list_for_linguist(
        db, str(current_user.id), status_filter=qc_status, skip=skip, limit=limit,
    )

    items: list[QueueItem] = []
    for job in jobs:
        job_id = str(job["_id"])
        for assignment in job.get("_my_assignments", []):
            lang = assignment["lang"]
            state_raw = (job.get("language_qc") or {}).get(lang, {})
            items.append(QueueItem(
                job_id=job_id,
                job_title=job.get("title", ""),
                job_status=job.get("status", ""),
                lang=lang,
                lang_qc_status=assignment.get("status", "pending"),
                assigned_at=state_raw.get("assigned_at").isoformat() if isinstance(state_raw, dict) and state_raw.get("assigned_at") else None,
                reviewed_at=state_raw.get("reviewed_at").isoformat() if isinstance(state_raw, dict) and state_raw.get("reviewed_at") else None,
            ))

    return QueueResponse(items=items, total=len(items))
