from __future__ import annotations
from typing import Dict, List, Tuple
import re
import difflib
import logging
from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse
from app.web.deps import templates, sb, motie_person_keys

router = APIRouter()
log = logging.getLogger("gov.motie.heads")

# person key utilities are provided from deps (motie_person_keys)

# === 고정 순서/기대 직위(표시용) ===
MOTIE_ORDER_POS: List[Tuple[str, int, str]] = [
    ("장관실",0,"장관"),
    ("대변인",1,"대변인"),
    ("홍보담당관",2,"과장"),
    ("홍보지원팀",2,"팀장"),
    ("감사관",1,"감사관"),
    ("감사담당관",2,"과장"),
    ("제1차관",0,"1차관"),
    ("운영지원과",1,"과장"),
    ("기획조정실",1,"실장"),
      ("정책기획관",2,"국장"),
        ("기획재정담당관",3,"과장"),
        ("혁신행정담당관",3,"과장"),
        ("규제개혁법무담당관",3,"과장"),
        ("정보관리담당관",3,"과장"),
        ("정보보호담당관",3,"과장"),
      ("비상안전기획관",2,"국장"),
        ("산업재난담당관",3,"과장"),
    ("산업정책실",1,"실장"),
      ("산업정책관",2,"국장"),
        ("산업정책과",3,"과장"),
        ("산업일자리혁신과",3,"과장"),
        ("산업환경과",3,"과장"),
        ("산업인공지능혁신과",3,"과장"),
        ("기업정책팀",3,"팀장"),
      ("산업공급망정책관",2,"국장"),
        ("산업공급망정책과",3,"과장"),
        ("소재부품장비개발과",3,"과장"),
        ("철강세라믹과",3,"과장"),
        ("화학산업팀",3,"팀장"),
      ("제조산업정책관",2,"국장"),
        ("기계로봇제조정책과",3,"과장"),
        ("자동차과",3,"과장"),
        ("조선해양플랜트과",3,"과장"),
        ("엔지니어링디자인과",3,"과장"),
        ("첨단민군혁신지원과",3,"과장"),
      ("첨단산업정책관",2,"국장"),
        ("반도체과",3,"과장"),
        ("배터리전기전자과",3,"과장"),
        ("바이오융합산업과",3,"과장"),
        ("섬유탄소나노과",3,"과장"),
        ("디스플레이가전팀",3,"팀장"),
    ("산업기반실",1,"실장"),
      ("산업기술융합정책관",2,"국장"),
        ("산업기술정책과",3,"과장"),
        ("산업기술개발과",3,"과장"),
        ("산업기술시장혁신과",3,"과장"),
        ("규제샌드박스팀",3,"팀장"),
      ("지역경제정책관",2,"국장"),
        ("지역경제총괄과",3,"과장"),
        ("지역경제진흥과",3,"과장"),
        ("입지총괄과",3,"과장"),
      ("중견기업정책관",2,"국장"),
        ("중견기업정책과",3,"과장"),
        ("중견기업지원과",3,"과장"),
        ("유통물류과",3,"과장"),
    ("제2차관",0,"2차관"),
    ("에너지정책실",1,"실장"),
      ("에너지정책관",2,"국장"),
        ("에너지정책과",3,"과장"),
        ("에너지효율과",3,"과장"),
        ("에너지기술과",3,"과장"),
      ("전력정책관",2,"국장"),
        ("전력산업정책과",3,"과장"),
        ("전력시장과",3,"과장"),
        ("신산업분산에너지과",3,"과장"),
        ("전력계통혁신과",3,"과장"),
      ("재생에너지정책관",2,"국장"),
        ("재생에너지정책과",3,"과장"),
        ("재생에너지산업과",3,"과장"),
        ("재생에너지보급과",3,"과장"),
      ("수소경제정책관",2,"국장"),
        ("수소경제정책과",3,"과장"),
        ("수소산업과",3,"과장"),
        ("에너지안전과",3,"과장"),
    ("자원산업정책국",1,"국장"),
      ("자원안보정책과",2,"과장"),
      ("석유산업과",2,"과장"),
      ("가스산업과",2,"과장"),
      ("석탄산업과",2,"과장"),
      ("광물자원팀",2,"팀장"),
    ("원전산업정책국",1,"국장"),
      ("원전산업정책과",2,"과장"),
      ("원전환경과",2,"과장"),
      ("원전지역협력과",2,"과장"),
    ("원전전략기획관",1,"국장"),
      ("원전수출진흥과",2,"과장"),
      ("원전수출협력과",2,"과장"),
    ("통상교섭본부장실",0,"통상교섭본부장"),
      ("통상차관보",1,"통상차관보"),
    ("통상정책국",1,"국장"),
      ("통상정책총괄과",2,"과장"),
      ("미주통상과",2,"과장"),
      ("구주통상과",2,"과장"),
      ("중남미대양주통상팀",2,"팀장"),
    ("신통상전략지원관",1,"국장"),
      ("신통상전략과",2,"과장"),
      ("디지털경제통상과",2,"과장"),
      ("기후에너지통상과",2,"과장"),
    ("통상협력국",1,"국장"),
      ("통상협력총괄과",2,"과장"),
      ("동북아통상과",2,"과장"),
      ("아주통상과",2,"과장"),
      ("중동아프리카통상과",2,"과장"),
    ("통상교섭실",1,"실장"),
      ("자유무역협정정책관",2,"국장"),
        ("자유무역협정정책기획과",3,"과장"),
        ("자유무역협정이행과",3,"과장"),
        ("통상협정활용과",3,"과장"),
        ("인도태평양통상기획팀",3,"팀장"),
      ("자유무역협정교섭관",2,"국장"),
        ("자유무역협정협상총괄과",3,"과장"),
        ("자유무역협정상품과",3,"과장"),
        ("자유무역협정서비스투자과",3,"과장"),
        ("자유무역협정무역규범과",3,"과장"),
      ("다자통상법무관",2,"국장"),
        ("통상법무기획과",3,"과장"),
        ("세계무역기구과",3,"과장"),
        ("다자통상협력과",3,"과장"),
        ("통상분쟁대응과",3,"과장"),
    ("무역투자실",1,"실장"),
      ("무역정책관",2,"국장"),
        ("무역정책과",3,"과장"),
        ("무역진흥과",3,"과장"),
        ("수출입과",3,"과장"),
      ("투자정책관",2,"국장"),
        ("투자정책과",3,"과장"),
        ("투자유치과",3,"과장"),
        ("해외투자과",3,"과장"),
      ("무역안보정책관",2,"국장"),
        ("무역안보정책과",3,"과장"),
        ("무역안보심사과",3,"과장"),
        ("기술안보과",3,"과장"),
    ("국가기술표준원",1,"원장"),
      ("원장실",2,"실장"),
      ("지원총괄과",2,"과장"),
      ("표준정책국",2,"국장"),
        ("표준정책과",3,"과장"),
        ("국제표준협력과",3,"과장"),
        ("산업표준혁신과",3,"과장"),
        ("전기전자정보표준과",3,"과장"),
        ("기계융합산업표준과",3,"과장"),
        ("바이오화학서비스표준과",3,"과장"),
        ("국제표준화기구전략대응팀",3,"팀장"),
      ("제품안전정책국",2,"국장"),
        ("제품안전정책과",3,"과장"),
        ("제품시장관리과",3,"과장"),
        ("제품안전정보과",3,"과장"),
        ("전기통신제품안전과",3,"과장"),
        ("생활어린이제품안전과",3,"과장"),
      ("적합성정책국",2,"국장"),
        ("시험인증정책과",3,"과장"),
        ("적합성평가과",3,"과장"),
        ("인증산업진흥과",3,"과장"),
        ("계량측정제도과",3,"과장"),
      ("기술규제대응국",2,"국장"),
        ("기술규제정책과",3,"과장"),
        ("무역기술장벽협상과",3,"과장"),
        ("기술규제조정과",3,"과장"),
        ("기술규제협력과",3,"과장"),
    ("무역위원회",1,"위원장"),
      ("상임위원",2,"상임위원"),
      ("무역조사실",2,"국장"),
        ("무역구제정책과",3,"과장"),
        ("산업피해조사과",3,"과장"),
        ("덤핑조사과",3,"과장"),
        ("덤핑조사지원과",3,"과장"),
        ("불공정무역조사과",3,"과장"),
        ("판정지원과",3,"과장"),
    ("광업등록사무소",1,"소장"),
      ("등록팀",2,"팀장"),
      ("심사팀",2,"팀장"),
    ("동부광산안전사무소",1,"소장"),
    ("중부광산안전사무소",1,"소장"),
    ("서부광산안전사무소",1,"소장"),
    ("남부광산안전사무소",1,"소장"),
    ("전기위원회",1,"위원장"),
      ("사무국",2,"사무국장"),
    ("경제자유구역기획단",1,"단장"),
      ("정책기획팀",2,"팀장"),
      ("혁신지원팀",2,"팀장"),
      ("서비스투자지원팀",2,"팀장"),
      ("개발투자지원팀",2,"팀장"),
    ("마산자유무역지역관리원",1,"원장"),
      ("관리과",2,"과장"),
      ("수출산업과",2,"과장"),
      ("투자홍보과",2,"과장"),
    ("군산자유무역지역관리원",1,"원장"),
      ("관리과",2,"과장"),
      ("수출산업과",2,"과장"),
      ("비상계획과",2,"과장"),
    ("대불자유무역지역관리원",1,"원장"),
      ("관리과",2,"과장"),
      ("수출산업과",2,"과장"),
    ("동해자유무역지역관리원",1,"원장"),
    ("율촌자유무역지역관리원",1,"원장"),
    ("김제자유무역지역관리원",1,"원장"),
      ("관리과",2,"과장"),
      ("수출산업과",2,"과장"),
    ("울산자유무역지역관리원",1,"원장"),
      ("관리과",2,"과장"),
      ("수출산업과",2,"과장"),
]

# ===== 정규화 유틸 =====
_INVISIBLES = re.compile(r"[\u200b\u200c\u200d\uFEFF]")  # zero-widths + BOM
def _norm(s: str) -> str:
    s = (s or "")
    s = s.replace("\u00A0", " ").replace("\u202F", " ").replace("\u3000", " ")
    s = _INVISIBLES.sub("", s)
    s = s.strip()
    s = re.sub(r"\s+", " ", s)
    return s

def _normalize_position(pos: str) -> str:
    p = _norm(pos)
    p = re.sub(r"\(.*?\)$", "", p).strip()
    p = re.sub(r"(직무대리|대행|겸임)$", "", p).strip()
    return p

def _normalize_department(dep: str) -> str:
    d = _norm(dep)
    d = d.replace("제 1차관", "제1차관").replace("제 2차관", "제2차관")
    d = d.replace("제 1차관실", "제1차관실").replace("제 2차관실", "제2차관실")
    return d

# === 부서 표준화(표기 변형 흡수) ===
DEPT_CANON_MAP = {
    "제1차관실": "제1차관",
    "제2차관실": "제2차관",
    "대변인실": "대변인",
}
def _canon_department(dep: str) -> str:
    d = _normalize_department(dep)
    return DEPT_CANON_MAP.get(d, d)

def _pick_best(cands: List[dict]) -> dict | None:
    if not cands:
        return None
    def score(x):
        has_phone = 1 if (x.get("phone") and str(x.get("phone")).strip() and str(x.get("phone")).strip() != "-") else 0
        return (has_phone, (x.get("name") or ""))
    return sorted(cands, key=score, reverse=True)[0]

@router.get("/gov/motie/heads", response_class=HTMLResponse)
async def gov_motie_heads_ordered(
    request: Request,
    q: str = Query(default=""),
    debug: int = Query(default=0),  # 0:off, 1:match, 2:+normalize, 3:+candidates
):
    # 0) 우선 DB 뷰(motie_heads_cur)가 있으면 그것을 사용 (정확도 우선)
    try:
        v = (
            sb.table("motie_heads_cur")
              .select("unit,position,name,phone,task,indent,ord")
              .order("ord", desc=False)
              .limit(5000)
              .execute()
              .data
        ) or []
    except Exception:
        v = []

    if v:
        items: List[dict] = []
        key = (q or "").strip().lower()
        for r in v:
            row = {
                "unit": r.get("unit"),
                "indent": r.get("indent") or 0,
                "name": (r.get("name") or "(공석)").strip() or "(공석)",
                "position": r.get("position"),
                "phone": (r.get("phone") or "-").strip() or "-",
                "task": (r.get("task") or "-").strip() or "-",
            }
            if row["name"] != "(공석)":
                keys = motie_person_keys(row.get("name"), None if row.get("phone") == '-' else row.get("phone"), row.get("unit"), row.get("position"))
                row["person_key"] = keys.get("display")
            hay = " ".join([str(x or "") for x in row.values()]).lower()
            if not key or key in hay:
                items.append(row)

        return templates.TemplateResponse(
            "gov/motie/heads.html",
            {
                "request": request,
                "ministry": "산업통상자원부(MOTIE)",
                "q": q,
                "items": items,
                "debug": debug,
                "dbg_lines": [
                    "[info] using motie_heads_cur view",
                    f"[info] rows={len(v)}",
                ],
                "misses": [],
            },
        )

    try:
        rows = (
            sb.table("motie_org_cur")
              .select("department,position,name,phone,task")
              .limit(50000)
              .execute()
              .data
        ) or []
    except Exception as e:
        log.exception("[heads] Supabase fetch failed: %s", e)
        rows = []

    dbg_lines: List[str] = []
    def _dbg(msg: str):
        # 화면에도 보여주기 위해 축적 + 서버 로그 출력
        dbg_lines.append(msg)
        if debug >= 1:
            log.debug(msg)

    _dbg(f"[heads] fetched_rows={len(rows)}")

    # 1) 강력 정규화 + 표준화
    norm_rows: List[dict] = []
    for i, r in enumerate(rows):
        dep_raw = r.get("department") or ""
        pos_raw = r.get("position") or ""
        dep = _canon_department(dep_raw)
        pos = _normalize_position(pos_raw)
        name = _norm(r.get("name") or "")
        phone = _norm(r.get("phone") or "")
        task = _norm(r.get("task") or "")
        rec = {
            "department_raw": dep_raw, "department": dep,
            "position_raw": pos_raw,   "position": pos,
            "name": name, "phone": phone, "task": task
        }
        norm_rows.append(rec)

        if debug >= 2:
            changed = (dep_raw != dep) or (pos_raw != pos)
            if changed or debug >= 3:
                _dbg(f"[normalize#{i}] dep:'{dep_raw}'→'{dep}', pos:'{pos_raw}'→'{pos}', name:'{name}', phone:'{phone}'")

    # 2) (dep, pos) 인덱스
    by_key: Dict[Tuple[str, str], List[dict]] = {}
    for r in norm_rows:
        dep = r["department"]; pos = r["position"]
        if dep and pos:
            by_key.setdefault((dep, pos), []).append(r)
    _dbg(f"[heads] unique_keys={len(by_key)}")

    key = _norm(q).lower()
    items: List[dict] = []
    misses: List[Tuple[str, str]] = []

    # 3) 공식 순서에 맞춘 ‘엄격 매칭’ (없으면 무조건 공석)
    for unit, indent, expected_pos in MOTIE_ORDER_POS:
        dep_norm = _canon_department(unit)
        pos_norm = _normalize_position(expected_pos)

        cands = by_key.get((dep_norm, pos_norm), [])
        rec = _pick_best(cands)

        if rec:
            name  = rec["name"] or "(공석)"
            pos   = rec["position"] or pos_norm
            phone = rec["phone"] or "-"
            task  = rec["task"] or "-"
            if debug >= 1:
                _dbg(f"[match] OK unit='{unit}', key=('{dep_norm}','{pos_norm}'), picked='{name}', phone='{phone}' (cands={len(cands)})")
                if debug >= 3:
                    # 후보 상세
                    for j, c in enumerate(cands):
                        _dbg(f"  └ cand[{j}] name='{c['name']}', pos='{c['position']}', phone='{c['phone']}'")
        else:
            name, pos, phone, task = "(공석)", pos_norm, "-", "-"
            misses.append((dep_norm, pos_norm))
            if debug >= 1:
                # 근접 후보 추천(참고용 로그)
                dep_keys = list({d for d, _ in by_key.keys()})
                pos_keys = list({p for _, p in by_key.keys()})
                near_dep = difflib.get_close_matches(dep_norm, dep_keys, n=3, cutoff=0.6)
                near_pos = difflib.get_close_matches(pos_norm, pos_keys, n=3, cutoff=0.6)
                _dbg(f"[match] MISS unit='{unit}', key=('{dep_norm}','{pos_norm}') near_dep={near_dep} near_pos={near_pos}")

        row = {
            "unit": unit, "indent": indent,
            "name": name, "position": pos, "phone": phone, "task": task,
        }
        if name != "(공석)":
            keys = motie_person_keys(name, None if phone == '-' else phone, unit, pos)
            row["person_key"] = keys.get("display")
        if not key or key in (" ".join([unit, name, pos, phone, task]).lower()):
            items.append(row)

    # 템플릿 렌더
    return templates.TemplateResponse(
        "gov/motie/heads.html",
        {
            "request": request,
            "ministry": "산업통상자원부(MOTIE)",
            "q": q,
            "items": items,
            "debug": debug,
            "dbg_lines": dbg_lines,   # 화면 하단 디버그 패널로 전달
            "misses": misses,         # 필요시 추가 표현 가능
        },
    )
