"""VTT version control endpoints."""

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

from ...core.authz import MembershipContext, get_job_or_403, get_membership_context
from ...core.config import settings
from ...core.database import get_database
from ...core.dependencies import require_roles
from ...models.audit_log import AuditAction
from ...models.user import User, UserRole
from ...models.vtt_version import (
    VttDiffResponse,
    VttKind,
    VttVersionListResponse,
    VttVersionSummary,
)
from ...services import vtt_versioning
from ...services.audit_logger import audit_logger
from ...services.gcs import gcs_service

router = APIRouter(prefix="/jobs", tags=["vtt-versions"])

_EDITABLE_ROLES = (UserRole.REVIEWER, UserRole.LINGUIST, UserRole.PRODUCTION, UserRole.ADMIN)


@router.get("/{job_id}/vtt/versions", response_model=VttVersionListResponse)
async def list_vtt_versions(
    job_id: str,
    lang: str = Query(...),
    kind: VttKind = Query(...),
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    current_user: User = Depends(require_roles(*_EDITABLE_ROLES)),
    ctx: MembershipContext = Depends(get_membership_context),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """List all VTT versions for a job/lang/kind, newest first."""
    await get_job_or_403(job_id, ctx, db)  # org check
    return await vtt_versioning.list_versions(db, job_id, lang, kind, skip, limit)


@router.get("/{job_id}/vtt/versions/{version}", response_model=dict)
async def get_vtt_version(
    job_id: str,
    version: int,
    lang: str = Query(...),
    kind: VttKind = Query(...),
    current_user: User = Depends(require_roles(*_EDITABLE_ROLES)),
    ctx: MembershipContext = Depends(get_membership_context),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Get full VTT content for a specific version."""
    await get_job_or_403(job_id, ctx, db)  # org check
    v = await vtt_versioning.get_version(db, job_id, lang, kind, version)
    if not v:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Version not found")
    return {
        "job_id": v.job_id,
        "lang": v.lang,
        "kind": v.kind,
        "version": v.version,
        "content": v.content,
        "gcs_uri": v.gcs_uri,
        "created_at": v.created_at.isoformat(),
        "created_by": v.created_by.dict(),
        "note": v.note,
        "parent_version": v.parent_version,
        "cue_count": v.cue_count,
        "byte_size": v.byte_size,
    }


@router.get("/{job_id}/vtt/versions/diff", response_model=VttDiffResponse)
async def diff_vtt_versions(
    job_id: str,
    lang: str = Query(...),
    kind: VttKind = Query(...),
    from_version: int = Query(..., alias="from"),
    to_version: int = Query(..., alias="to"),
    current_user: User = Depends(require_roles(*_EDITABLE_ROLES)),
    ctx: MembershipContext = Depends(get_membership_context),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """Line-level diff between two versions of a VTT file."""
    await get_job_or_403(job_id, ctx, db)  # org check
    v_from = await vtt_versioning.get_version(db, job_id, lang, kind, from_version)
    v_to = await vtt_versioning.get_version(db, job_id, lang, kind, to_version)
    if not v_from:
        raise HTTPException(status_code=404, detail=f"Version {from_version} not found")
    if not v_to:
        raise HTTPException(status_code=404, detail=f"Version {to_version} not found")
    return vtt_versioning.diff_versions(job_id, lang, kind, v_from, v_to)


@router.post(
    "/{job_id}/vtt/versions/{version}/restore",
    response_model=VttVersionSummary,
    status_code=status.HTTP_201_CREATED,
)
async def restore_vtt_version(
    job_id: str,
    version: int,
    lang: str = Query(...),
    kind: VttKind = Query(...),
    http_request: Request = None,
    current_user: User = Depends(require_roles(UserRole.PRODUCTION, UserRole.ADMIN)),
    ctx: MembershipContext = Depends(get_membership_context),
    db: AsyncIOMotorDatabase = Depends(get_database),
):
    """
    Restore a previous version as the new live VTT.
    Non-destructive: creates a new version entry whose content mirrors the old one,
    then overwrites the live GCS file.
    """
    await get_job_or_403(job_id, ctx, db)  # org check
    src = await vtt_versioning.get_version(db, job_id, lang, kind, version)
    if not src:
        raise HTTPException(status_code=404, detail="Version not found")

    # Create new version snapshot (this also bumps the counter)
    new_ver = await vtt_versioning.restore_version(db, job_id, lang, kind, version, current_user)

    # Overwrite the live file in GCS so the QC editor sees the restored content
    live_path = f"{job_id}/{lang}/{'captions' if kind == 'captions' else 'ad'}.vtt"
    try:
        await gcs_service.upload_text_to_gcs(src.content, live_path, "text/vtt")
    except Exception as exc:
        raise HTTPException(
            status_code=500,
            detail=f"Version snapshot created (v{new_ver.version}) but live file update failed: {exc}",
        ) from None

    # Update the GCS URI pointer in the job document
    gcs_uri_key = "captions_vtt_gcs" if kind == "captions" else "ad_vtt_gcs"
    new_gcs_uri = f"gs://{settings.gcs_bucket}/{live_path}"
    await db.jobs.update_one(
        {"_id": job_id},
        {"$set": {f"outputs.{lang}.{gcs_uri_key}": new_gcs_uri}},
    )

    await audit_logger.log_action(
        action=AuditAction.VTT_EDIT,
        description=f"VTT restored to v{version} for job {job_id} lang={lang} kind={kind}",
        user=current_user,
        request=http_request,
        resource_type="job",
        resource_id=job_id,
        details={"lang": lang, "kind": kind, "restored_from_version": version, "new_version": new_ver.version},
    )
    return new_ver
