from __future__ import annotations
from typing import Any, Dict, List
from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse, StreamingResponse
import io, csv
from app.web.deps import templates, sb, logger, motie_person_keys

router = APIRouter()

@router.get("/gov/search", response_class=HTMLResponse)
async def gov_search(
    request: Request,
    src: str = Query(default="all"),
    q: str = Query(default=""),
    page: int = Query(default=1, ge=1),
    limit: int = Query(default=100, ge=1, le=1000),
):
    q_norm = (q or "").strip()
    rows: List[Dict[str, Any]] = []
    if not q_norm:
        return templates.TemplateResponse("gov/search.html", {"request": request, "src": src, "q": q_norm, "rows": rows, "page": page, "limit": limit})

    try:
        query = sb.table("gov_staff_cur").select("source,department,position,name,phone,task")
        if src in ("MOTIE", "MOEF", "ME"):
            query = query.eq("source", src)
        kw = f"%{q_norm}%"
        query = query.or_(f"name.ilike.{kw},department.ilike.{kw},position.ilike.{kw},task.ilike.{kw},phone.ilike.{kw}")
        # pagination
        try:
            offset = (page - 1) * limit
            rows = query.range(offset, offset + limit - 1).execute().data or []
        except Exception:
            rows = query.limit(limit).execute().data or []
    except Exception as e:
        logger.warning(f"gov_staff search fallback (reason: {e})")
        try:
            q2 = sb.table("gov_staff").select("source,department,position,name,phone,task")
            if src in ("MOTIE", "MOEF", "ME"):
                q2 = q2.eq("source", src)
            data = (q2.limit(5000).execute().data) or []
            key = q_norm.lower()
            def hit(r):
                return any(key in (r.get(f, "") or "").lower() for f in ("name","department","position","task","phone"))
            rows = [r for r in data if hit(r)]
            start = (page - 1) * limit
            rows = rows[start:start+limit]
        except Exception:
            rows = []

    # attach person_key for MOTIE results to link person page
    try:
        for r in rows:
            if (r.get('source') or '').upper() == 'MOTIE':
                keys = motie_person_keys(r.get('name'), r.get('phone'), r.get('department'), r.get('position'))
                r['person_key'] = keys.get('display')
    except Exception:
        pass

    rows.sort(key=lambda r: (r.get("department", "") or "", r.get("name", "") or ""))
    return templates.TemplateResponse("gov/search.html", {"request": request, "src": src, "q": q_norm, "rows": rows, "page": page, "limit": limit})


@router.get("/gov/search.csv")
async def gov_search_csv(
    src: str = Query(default="all"),
    q: str = Query(default=""),
    limit: int = Query(default=5000, ge=1, le=20000),
):
    q_norm = (q or "").strip()
    rows: List[Dict[str, Any]] = []
    if q_norm:
        try:
            query = sb.table("gov_staff_cur").select("source,department,position,name,phone,task")
            if src in ("MOTIE", "MOEF", "ME"):
                query = query.eq("source", src)
            kw = f"%{q_norm}%"
            query = query.or_(f"name.ilike.{kw},department.ilike.{kw},position.ilike.{kw},task.ilike.{kw},phone.ilike.{kw}")
            rows = query.limit(limit).execute().data or []
        except Exception:
            rows = []
    # CSV build
    output = io.StringIO()
    writer = csv.writer(output)
    writer.writerow(["source","department","position","name","phone","task"])
    for r in rows:
        writer.writerow([
            r.get("source",""), r.get("department",""), r.get("position",""),
            r.get("name",""), r.get("phone",""), r.get("task",""),
        ])
    output.seek(0)
    headers = {"Content-Disposition": "attachment; filename=gov_search.csv"}
    return StreamingResponse(iter([output.getvalue()]), media_type="text/csv", headers=headers)
