from __future__ import annotations
from typing import Any, Dict, List, Set, Tuple
import hashlib
from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse
from app.web.deps import templates, sb, logger
from collections import Counter

router = APIRouter()

PER_PAGE = 10

def _role_rank(txt: str) -> int:
    t = (txt or "").strip()
    if t.startswith("위원장"): return 0
    if t.startswith("간사"):   return 1
    return 2

def _label_election(n: Any) -> str:
    try:
        v = int(n)
    except Exception:
        return "-"
    if v == 1: return "초선"
    if v == 2: return "재선"
    return f"{v}선"

def _district_br(v: str | None) -> str:
    s = (v or "").strip()
    return "<br>".join(s.split()) if s else ""

def _person_key(full_name: str | None, room_no: str | None) -> str:
    base = f"{(full_name or '').strip()}|{(room_no or '').strip()}"
    return hashlib.sha1(base.encode('utf-8')).hexdigest()

async def _distinct_values(col: str) -> List[str]:
    try:
        rows = sb.table("congress_member_cur").select(col).limit(10000).execute().data or []
    except Exception as e:
        logger.warning(f"distinct fetch fallback for {col}: {e}")
        rows = []
    vals: Set[str] = set()
    for r in rows:
        v = (r.get(col) or "").strip()
        if v:
            vals.add(v)
    return sorted(vals)

@router.get("/congress/search", response_class=HTMLResponse)
async def congress_search(
    request: Request,
    committee: str = Query(default="all"),
    party: str = Query(default="all"),
    q: str = Query(default=""),
    page: int = Query(default=1, ge=1),
):
    q_norm = (q or "").strip()
    committees = await _distinct_values("committee_name")
    parties    = await _distinct_values("party")

    # 공통 쿼리(필터: 서버측은 위원회/정당만 — 키워드는 로컬에서 일괄 처리)
    def apply_filters(query):
        if committee != "all":
            query = query.eq("committee_name", committee)
        if party != "all":
            query = query.eq("party", party)
        return query

    total = 0
    rows: List[Dict[str, Any]] = []
    try:
        if q_norm:
            # 키워드가 있으면 서버에서 기본 필터만 적용 후 로컬 검색으로 안정 처리
            data = (apply_filters(sb.table("congress_member_cur")
                    .select("committee_name,role_name,full_name,name_hanja,party,district,phone,room_no,"
                            "photo_url,member_page_url,aide_staff,aide_secretary,aide_secretary2,election_count")
                    .limit(10000))
                    .execute().data) or []
            key = q_norm.lower()
            filtered = []
            for r in data:
                tgt = " ".join([
                    (r.get("full_name") or ""), (r.get("name_hanja") or ""), (r.get("party") or ""),
                    (r.get("district") or ""), (r.get("role_name") or "")
                ]).lower()
                if key in tgt:
                    filtered.append(r)
            total = len(filtered)
            start = (page - 1) * PER_PAGE
            end   = start + PER_PAGE
            rows = filtered[start:end]
        else:
            # 키워드 없으면 서버 페이징 + 정확 카운트 사용
            base = sb.table("congress_member_cur").select("*", count="exact")
            total_resp = apply_filters(base).range(0, 0).execute()
            total = getattr(total_resp, "count", None) or (len(total_resp.data or []))
            start = (page - 1) * PER_PAGE
            end   = start + PER_PAGE - 1
            q2 = sb.table("congress_member_cur").select(
                "committee_name,role_name,full_name,name_hanja,party,district,phone,room_no,"
                "photo_url,member_page_url,aide_staff,aide_secretary,aide_secretary2,election_count"
            )
            q2 = apply_filters(q2).range(start, end)
            rows = q2.execute().data or []
    except Exception as e:
        logger.warning(f"congress_member search fallback (reason: {e})")
        rows = []
        total = 0

    rows.sort(key=lambda r: (_role_rank(r.get("role_name","")), r.get("full_name","")))
    for r in rows:
        r["election_label"] = _label_election(r.get("election_count"))
        r["district_br"] = _district_br(r.get("district"))
        try:
            r["person_key"] = _person_key(r.get("full_name"), r.get("room_no"))
        except Exception:
            r["person_key"] = None

    has_prev = page > 1
    has_next = (page * PER_PAGE) < (total or 0)

    return templates.TemplateResponse("congress/search.html", {
        "request": request,
        "committee": committee, "party": party, "q": q_norm,
        "committees": committees, "parties": parties,
        "rows": rows,
        "page": page, "has_prev": has_prev, "has_next": has_next,
        "per_page": PER_PAGE, "total": total,
    })
