"""Crawl trigger + detail page. Background worker lives here too."""

import json
import threading
from pathlib import Path

from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse

from db import execute, query_one
from deps import CRAWLS_DIR, CRAWL_MAX_PAGES, audit, render, require_internal

router = APIRouter()


@router.post("/clients/{client_id}/crawls")
def crawl_start(request: Request, client_id: int):
    user = require_internal(request)
    client = query_one("SELECT id, primary_url FROM client WHERE id = ?", (client_id,))
    if not client:
        raise HTTPException(404)
    crawl_id = execute(
        "INSERT INTO crawl_run (client_id, status) VALUES (?, 'pending')", (client_id,)
    )
    crawl_dir = CRAWLS_DIR / str(crawl_id)
    crawl_dir.mkdir(parents=True, exist_ok=True)
    execute("UPDATE crawl_run SET screenshots_dir = ? WHERE id = ?",
            (str(crawl_dir), crawl_id))
    audit(user.id, client_id, "crawl.start", {"crawl_id": crawl_id})

    threading.Thread(
        target=_run_crawl_and_analyze,
        args=(crawl_id, client_id, client["primary_url"], crawl_dir),
        daemon=True,
    ).start()

    return RedirectResponse(f"/crawls/{crawl_id}", status_code=303)


def _run_crawl_and_analyze(crawl_id: int, client_id: int,
                           target_url: str, crawl_dir: Path) -> None:
    """Background worker: crawl → analyze → create report."""
    from crawler.playwright_runner import crawl as run_crawl
    execute("UPDATE crawl_run SET status = 'running' WHERE id = ?", (crawl_id,))
    try:
        result = run_crawl(target_url, crawl_dir, max_pages=CRAWL_MAX_PAGES)
        pages_json = json.dumps([{
            "index": p.index, "url": p.url, "title": p.title, "status": p.status,
            "duration_ms": p.duration_ms, "error": p.error, "dir_name": p.dir_name,
            "interactive_summary": p.interactive_summary,
        } for p in result.pages])
        if result.error and not result.pages:
            execute(
                "UPDATE crawl_run SET status='failed', finished_at=CURRENT_TIMESTAMP, "
                "error=?, pages_crawled_json=? WHERE id=?",
                (result.error, pages_json, crawl_id),
            )
            audit(None, client_id, "crawl.failed",
                  {"crawl_id": crawl_id, "error": result.error})
            return
        execute("UPDATE crawl_run SET pages_crawled_json=? WHERE id=?",
                (pages_json, crawl_id))

        try:
            from reports.builder import analyze_and_build_report
            report_id, spend_cents, model = analyze_and_build_report(
                crawl_id=crawl_id, client_id=client_id, crawl_dir=crawl_dir,
                pages=result.pages, target_url=target_url,
            )
            execute(
                "UPDATE crawl_run SET status='done', finished_at=CURRENT_TIMESTAMP, "
                "ai_spend_cents=?, claude_model=? WHERE id=?",
                (spend_cents, model, crawl_id),
            )
            audit(None, client_id, "crawl.done",
                  {"crawl_id": crawl_id, "report_id": report_id, "spend_cents": spend_cents})
        except Exception as e:
            execute(
                "UPDATE crawl_run SET status='failed', finished_at=CURRENT_TIMESTAMP, error=? WHERE id=?",
                (f"analyzer error: {type(e).__name__}: {e}", crawl_id),
            )
            audit(None, client_id, "crawl.analyzer_failed",
                  {"crawl_id": crawl_id, "error": str(e)})
    except Exception as e:
        execute(
            "UPDATE crawl_run SET status='failed', finished_at=CURRENT_TIMESTAMP, error=? WHERE id=?",
            (f"{type(e).__name__}: {e}", crawl_id),
        )
        audit(None, client_id, "crawl.failed",
              {"crawl_id": crawl_id, "error": str(e)})


@router.get("/crawls/{crawl_id}", response_class=HTMLResponse)
def crawl_detail(request: Request, crawl_id: int):
    user = require_internal(request)
    crawl = query_one(
        """SELECT cr.*, c.id AS client_id, c.name AS client_name, c.primary_url
           FROM crawl_run cr JOIN client c ON c.id = cr.client_id
           WHERE cr.id = ?""", (crawl_id,)
    )
    if not crawl:
        raise HTTPException(404)
    pages = json.loads(crawl["pages_crawled_json"]) if crawl["pages_crawled_json"] else []
    report = query_one(
        "SELECT id, title, status FROM report WHERE crawl_run_id = ? ORDER BY id DESC LIMIT 1",
        (crawl_id,)
    )
    return render("crawl_detail.html", user=user, crawl=crawl, pages=pages, report=report)
