from __future__ import annotations

from typing import Dict, Any, Optional, List

from fastapi import APIRouter, Depends, Header
from fastapi.responses import JSONResponse

from .deps import require_api_key

import time
import threading
import uuid

router = APIRouter(prefix="/api/v1/tradeshow", tags=["tradeshow"])


@router.post("/enrich/dry-run")
def enrich_dry_run(payload: Dict, api_ctx=Depends(require_api_key)):
    """Estimate enrichment coverage and cost (stub for v1.1).

    Expects: {"fields": [...], "stats": {"rows": int, ...}}
    Returns: {"provider": "pdl", "est_coverage": float, "est_cost": float}
    """
    rows = 0
    try:
        rows = int(((payload or {}).get("stats") or {}).get("rows") or 0)
    except Exception:
        rows = 0

    # Placeholder estimates
    est_cov = 0.55
    est_cost = round(rows * 0.15, 2)

    res = JSONResponse(
        content={"provider": "pdl", "est_coverage": est_cov, "est_cost": est_cost}
    )
    res.headers["Cache-Control"] = "no-store"
    return res


# ---- In-memory job store (swap to Redis/RQ later) ----
_JOBS: Dict[str, Dict[str, Any]] = {}
_JOBS_LOCK = threading.Lock()


def _new_job_id() -> str:
    return uuid.uuid4().hex


def _set_job(jid: str, data: Dict[str, Any]) -> None:
    with _JOBS_LOCK:
        _JOBS[jid] = data


def _get_job(jid: str) -> Optional[Dict[str, Any]]:
    with _JOBS_LOCK:
        return _JOBS.get(jid)


def _background_enrich(
    jid: str, headers: List[str], rows: List[List[Any]], fields: List[str]
) -> None:
    try:
        total = len(rows)
        chunk = 50
        credits_used_total = 0.0
        processed = 0
        enriched_rows: List[List[Any]] = []

        used_provider = "pdl"
        while processed < total:
            end = min(processed + chunk, total)
            batch = rows[processed:end]
            # Prefer People Data Labs adapter; fall back to Apollo, then pass-through
            try:
                from ...integrations.people_data_labs import PeopleDataLabsAdapter

                pdl = PeopleDataLabsAdapter()
                if pdl.available():
                    # Heuristic: decide enrichment type based on headers
                    hdr_l = [str(h or "").strip().lower() for h in headers]
                    enrich_type = (
                        "person"
                        if ("email" in hdr_l or "work_email" in hdr_l)
                        else "company"
                    )
                    enr_rows, credits = pdl.enrich_batch(
                        headers, batch, fields, enrich_type=enrich_type
                    )
                    credits_used_total += float(credits or 0.0)
                    enriched_rows.extend(enr_rows or batch)
                else:
                    raise RuntimeError("PDL not configured")
            except Exception:
                try:
                    from ...integrations.apollo import ApolloAdapter

                    adapter = ApolloAdapter()
                    if adapter.available():
                        enr_rows, credits = adapter.enrich_batch(headers, batch, fields)
                        used_provider = "apollo"
                        credits_used_total += float(credits or 0.0)
                        enriched_rows.extend(enr_rows or batch)
                    else:
                        enriched_rows.extend(batch)
                except Exception:
                    enriched_rows.extend(batch)
            processed = end
            st = _get_job(jid) or {}
            st.update(
                {
                    "status": "processing",
                    "processed_rows": processed,
                    "total_rows": total,
                    "credits_used": round(credits_used_total, 2),
                    "updated_at": time.time(),
                }
            )
            _set_job(jid, st)

        st = _get_job(jid) or {}
        st.update(
            {
                "status": "completed",
                "processed_rows": total,
                "total_rows": total,
                "credits_used": round(credits_used_total, 2),
                "result": {
                    "headers": headers,
                    "rows": enriched_rows,
                    "provider": used_provider,
                    "fields": fields,
                },
                "updated_at": time.time(),
            }
        )
        _set_job(jid, st)
    except Exception as e:
        st = _get_job(jid) or {}
        st.update({"status": "failed", "error": str(e), "updated_at": time.time()})
        _set_job(jid, st)


@router.post("/enrich")
def enrich_start(
    payload: Dict[str, Any],
    api_ctx=Depends(require_api_key),
    idempotency_key: Optional[str] = Header(
        default=None, convert_underscores=False, alias="Idempotency-Key"
    ),
):
    src = (payload or {}).get("source") or {}
    headers: List[str] = list(src.get("headers") or [])
    rows: List[List[Any]] = list(src.get("rows") or [])
    fields: List[str] = list((payload or {}).get("fields") or [])

    if idempotency_key:
        j = _get_job(idempotency_key)
        if j:
            res = JSONResponse(content={"job_id": idempotency_key})
            res.headers["Cache-Control"] = "no-store"
            return res

    job_id = idempotency_key or _new_job_id()
    _set_job(
        job_id,
        {
            "status": "queued",
            "processed_rows": 0,
            "total_rows": len(rows),
            "credits_used": 0.0,
            "created_at": time.time(),
            "updated_at": time.time(),
        },
    )
    t = threading.Thread(
        target=_background_enrich, args=(job_id, headers, rows, fields), daemon=True
    )
    t.start()
    res = JSONResponse(content={"job_id": job_id})
    res.headers["Cache-Control"] = "no-store"
    return res


@router.get("/enrich/{job_id}/status")
def enrich_status(job_id: str, api_ctx=Depends(require_api_key)):
    st = _get_job(job_id)
    if not st:
        res = JSONResponse(
            content={"ok": False, "error": "JOB_NOT_FOUND"}, status_code=404
        )
        res.headers["Cache-Control"] = "no-store"
        return res
    out = {
        "status": st["status"],
        "processed_rows": st["processed_rows"],
        "total_rows": st["total_rows"],
        "credits_used": st.get("credits_used", 0.0),
        "updated_at": st.get("updated_at"),
    }
    res = JSONResponse(content=out)
    res.headers["Cache-Control"] = "no-store"
    return res


@router.get("/enrich/{job_id}/results")
def enrich_results(
    job_id: str, api_ctx=Depends(require_api_key), limit: int = 0, offset: int = 0
):
    st = _get_job(job_id)
    if not st:
        res = JSONResponse(
            content={"ok": False, "error": "JOB_NOT_FOUND"}, status_code=404
        )
        res.headers["Cache-Control"] = "no-store"
        return res
    if st["status"] != "completed":
        res = JSONResponse(
            content={"ok": False, "error": "NOT_READY", "status": st["status"]},
            status_code=409,
        )
        res.headers["Cache-Control"] = "no-store"
        return res
    result = dict(st["result"])
    rows = list(result.get("rows") or [])
    if limit and limit > 0:
        start = max(0, int(offset or 0))
        end = min(len(rows), start + int(limit))
        result["rows"] = rows[start:end]
    res = JSONResponse(content={"ok": True, "result": result})
    res.headers["Cache-Control"] = "no-store"
    return res
