"""Rotas Desk — domínios VM112 (Spec 017)."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field

from app import auth, vm112_domains
from app.permissions import can_manage_vm112_domains
from app.vm112_purge_stream import purge_sse_generator
from app.vm112_purge_jobs import get_job_public, list_jobs, recover_job, start_job

router = APIRouter(prefix="/api/v1/vm112", tags=["vm112-domains"])


class DomainPurgeRequest(BaseModel):
    confirm_domain: str = Field(..., min_length=3)
    root_password: str = Field(..., min_length=1)


def _require_admin(user: auth.DeskUser = Depends(auth.get_current_user)) -> auth.DeskUser:
    if not can_manage_vm112_domains(user.role):
        raise HTTPException(403, "Apenas perfis Admin (super_admin, ops_lead)")
    return user


def _validate_purge_request(domain: str, body: DomainPurgeRequest) -> str:
    domain = domain.lower().strip()
    if domain in vm112_domains.PURGE_BLOCKLIST:
        raise HTTPException(400, f"Domínio {domain} está protegido contra purge")
    if body.confirm_domain.lower().strip() != domain:
        raise HTTPException(400, "Confirmação do domínio não coincide")
    return domain


@router.get("/domains")
def list_vm112_domains(
    q: str = "",
    user: auth.DeskUser = Depends(_require_admin),
):
    try:
        return vm112_domains.list_domains(q)
    except Exception as e:
        raise HTTPException(502, f"VM112 indisponível: {e}") from e


@router.get("/domains/{domain}")
def get_vm112_domain(
    domain: str,
    user: auth.DeskUser = Depends(_require_admin),
):
    try:
        return vm112_domains.get_domain(domain)
    except Exception as e:
        raise HTTPException(502, f"VM112: {e}") from e


@router.post("/domains/{domain}/purge")
def purge_vm112_domain(
    domain: str,
    body: DomainPurgeRequest,
    user: auth.DeskUser = Depends(_require_admin),
):
    domain = _validate_purge_request(domain, body)
    conn = auth.db()
    try:
        if not vm112_domains.verify_root_password(conn, body.root_password):
            raise HTTPException(403, "Senha Root incorrecta")
    finally:
        conn.close()
    try:
        vm112_result = vm112_domains.purge_vm112(domain)
    except Exception as e:
        raise HTTPException(502, f"Purge VM112 falhou: {e}") from e
    conn = auth.db()
    try:
        desk_counts, desk_timeline = vm112_domains.purge_desk_timeline(conn, domain)
    finally:
        conn.close()
    timeline = vm112_domains.build_purge_timeline(vm112_result, desk_counts, desk_timeline)
    return {
        "ok": True,
        "domain": domain,
        "vm112": vm112_result,
        "desk": desk_counts,
        "timeline": timeline,
        "by": user.username,
    }


@router.post("/domains/{domain}/purge/stream")
def purge_vm112_domain_stream(
    domain: str,
    body: DomainPurgeRequest,
    user: auth.DeskUser = Depends(_require_admin),
):
    """SSE — progresso purge em tempo real (Fase 2 Spec 017)."""
    domain = _validate_purge_request(domain, body)
    return StreamingResponse(
        purge_sse_generator(domain, body.root_password, user.username),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no",
        },
    )


@router.post("/domains/{domain}/purge/jobs")
def start_purge_job(
    domain: str,
    body: DomainPurgeRequest,
    user: auth.DeskUser = Depends(_require_admin),
):
    """Inicia purge em background; consultar GET /purge/jobs/{id} (recomendado via Traefik)."""
    domain = _validate_purge_request(domain, body)
    job_id = start_job(domain, body.root_password, user.username)
    return {"ok": True, "job_id": job_id, "domain": domain, "status": "running"}


@router.get("/purge/jobs")
def list_purge_jobs(
    limit: int = 100,
    offset: int = 0,
    user: auth.DeskUser = Depends(_require_admin),
):
    return list_jobs(limit=limit, offset=offset)


@router.get("/purge/jobs/{job_id}")
def get_purge_job_status(
    job_id: str,
    user: auth.DeskUser = Depends(_require_admin),
):
    job = get_job_public(job_id)
    if not job:
        raise HTTPException(404, "Job purge não encontrado")
    return job

@router.post("/purge/jobs/{job_id}/recover")
def recover_purge_job(
    job_id: str,
    domain: str = "",
    user: auth.DeskUser = Depends(_require_admin),
):
    """Recupera purge quando job sumiu da memória mas VM112 já removeu o domínio."""
    job = recover_job(job_id, domain or None)
    if not job:
        raise HTTPException(404, "Não foi possível recuperar o job purge")
    return job

