"""
Agent History Routes — persist and retrieve scan results.

GET  /api/compliance/agent/scans — list recent scans
GET  /api/compliance/agent/scans/{id} — get single scan
POST /api/compliance/agent/scans — save a scan result
"""

import json
import logging
import os
import uuid
from datetime import datetime, timezone

from fastapi import APIRouter, Query
from fastapi.responses import Response
from pydantic import BaseModel

from compliance.services.agent_pdf_export import generate_scan_pdf

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/compliance/agent", tags=["agent"])

DATABASE_URL = os.environ.get(
    "COMPLIANCE_DATABASE_URL",
    os.environ.get("DATABASE_URL", ""),
)


class SaveScanRequest(BaseModel):
    url: str
    scan_type: str = "scan"
    analysis_mode: str = "post_launch"
    result: dict  # Full scan result JSON


class ScanHistoryItem(BaseModel):
    id: str
    url: str
    scan_type: str
    analysis_mode: str
    risk_level: str | None = None
    risk_score: float = 0
    findings_count: int = 0
    pages_scanned: int = 0
    email_sent: bool = False
    created_at: str


class ScanDetail(BaseModel):
    id: str
    url: str
    scan_type: str
    analysis_mode: str
    result: dict
    created_at: str


async def _get_pool():
    """Get or create database connection pool."""
    import asyncpg
    if not DATABASE_URL:
        return None
    try:
        return await asyncpg.create_pool(DATABASE_URL, min_size=1, max_size=3)
    except Exception as e:
        logger.warning("DB connection failed: %s", e)
        return None


@router.post("/scans")
async def save_scan(req: SaveScanRequest):
    """Save a scan result to the database."""
    pool = await _get_pool()
    if not pool:
        return {"status": "skipped", "reason": "no database"}

    scan_id = str(uuid.uuid4())
    result = req.result

    try:
        async with pool.acquire() as conn:
            await conn.execute("""
                INSERT INTO compliance_agent_scans
                (id, url, scan_type, analysis_mode, classification, risk_level,
                 risk_score, escalation_level, responsible_role, services,
                 findings, summary_html, pages_scanned, pages_list, email_sent,
                 created_at)
                VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
            """,
                uuid.UUID(scan_id),
                req.url,
                req.scan_type,
                req.analysis_mode,
                result.get("classification", ""),
                result.get("risk_level", ""),
                result.get("risk_score", 0),
                result.get("escalation_level", ""),
                result.get("responsible_role", ""),
                json.dumps(result.get("services", [])),
                json.dumps(result.get("findings", [])),
                result.get("summary", result.get("summary_html", "")),
                result.get("pages_scanned", 0),
                json.dumps(result.get("pages_list", [])),
                result.get("email_status") == "sent",
                datetime.now(timezone.utc),
            )
        return {"status": "saved", "id": scan_id}
    except Exception as e:
        logger.error("Failed to save scan: %s", e)
        return {"status": "error", "error": str(e)}
    finally:
        await pool.close()


@router.get("/scans", response_model=list[ScanHistoryItem])
async def list_scans(
    limit: int = Query(20, le=100),
    scan_type: str | None = None,
):
    """List recent scans."""
    pool = await _get_pool()
    if not pool:
        return []

    try:
        async with pool.acquire() as conn:
            query = """
                SELECT id, url, scan_type, analysis_mode, risk_level, risk_score,
                       findings, pages_scanned, email_sent, created_at
                FROM compliance_agent_scans
            """
            params = []
            if scan_type:
                query += " WHERE scan_type = $1"
                params.append(scan_type)
            query += " ORDER BY created_at DESC LIMIT " + str(limit)

            rows = await conn.fetch(query, *params)
            return [
                ScanHistoryItem(
                    id=str(r["id"]),
                    url=r["url"],
                    scan_type=r["scan_type"],
                    analysis_mode=r["analysis_mode"],
                    risk_level=r["risk_level"],
                    risk_score=r["risk_score"] or 0,
                    findings_count=len(json.loads(r["findings"] or "[]")),
                    pages_scanned=r["pages_scanned"] or 0,
                    email_sent=r["email_sent"] or False,
                    created_at=r["created_at"].isoformat() if r["created_at"] else "",
                )
                for r in rows
            ]
    except Exception as e:
        logger.error("Failed to list scans: %s", e)
        return []
    finally:
        await pool.close()


@router.get("/scans/{scan_id}", response_model=ScanDetail)
async def get_scan(scan_id: str):
    """Get a single scan result."""
    pool = await _get_pool()
    if not pool:
        return ScanDetail(id=scan_id, url="", scan_type="", analysis_mode="", result={}, created_at="")

    try:
        async with pool.acquire() as conn:
            row = await conn.fetchrow("""
                SELECT * FROM compliance_agent_scans WHERE id = $1
            """, uuid.UUID(scan_id))

            if not row:
                return ScanDetail(id=scan_id, url="", scan_type="", analysis_mode="", result={}, created_at="")

            return ScanDetail(
                id=str(row["id"]),
                url=row["url"],
                scan_type=row["scan_type"],
                analysis_mode=row["analysis_mode"],
                result={
                    "classification": row["classification"],
                    "risk_level": row["risk_level"],
                    "risk_score": row["risk_score"],
                    "services": json.loads(row["services"] or "[]"),
                    "findings": json.loads(row["findings"] or "[]"),
                    "summary": row["summary_html"],
                    "pages_scanned": row["pages_scanned"],
                    "pages_list": json.loads(row["pages_list"] or "[]"),
                },
                created_at=row["created_at"].isoformat() if row["created_at"] else "",
            )
    except Exception as e:
        logger.error("Failed to get scan: %s", e)
        return ScanDetail(id=scan_id, url="", scan_type="", analysis_mode="", result={}, created_at="")
    finally:
        await pool.close()


@router.post("/scans/pdf")
async def export_scan_pdf(req: SaveScanRequest):
    """Generate a PDF report from scan results (no DB required)."""
    try:
        pdf_bytes = generate_scan_pdf({
            "url": req.url,
            "scan_type": req.scan_type,
            "analysis_mode": req.analysis_mode,
            **req.result,
        })
        return Response(
            content=pdf_bytes,
            media_type="application/pdf",
            headers={"Content-Disposition": f'attachment; filename="compliance-report-{req.url.split("/")[2][:30]}.pdf"'},
        )
    except Exception as e:
        logger.error("PDF generation failed: %s", e)
        return {"error": str(e)}
