import os
import asyncio
from pathlib import Path
from typing import Optional, List, Dict, Any
from datetime import datetime, date, timezone

from fastapi import FastAPI, Request, Query
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parents[2]
load_dotenv(BASE_DIR / ".env")

from app.services.supabase_service import get_supabase

app = FastAPI(title="GovBot Web")

# static (옵션)
static_dir = BASE_DIR / "app" / "web" / "static"
if static_dir.exists():
    app.mount("/static", StaticFiles(directory=static_dir), name="static")

templates = Jinja2Templates(directory=str(BASE_DIR / "app" / "web" / "templates"))

# ---------- 공용 유틸 ----------
def _to_str(v, default=""):
    try:
        return v if isinstance(v, str) else (str(v) if v is not None else default)
    except Exception:
        return default

def _parse_posted(v) -> date:
    """posted_at -> date. 없으면 date.min"""
    if isinstance(v, date):
        return v
    if not v:
        return date.min
    s = str(v)[:10].replace(".", "-").strip()
    try:
        y, m, d = s.split("-")
        return date(int(y), int(m), int(d))
    except Exception:
        return date.min

def _parse_created(v) -> datetime:
    """created_at -> timezone-aware UTC datetime"""
    if not v:
        return datetime.min.replace(tzinfo=timezone.utc)
    s = str(v).strip().replace("Z", "+00:00")
    try:
        dt = datetime.fromisoformat(s)
    except Exception:
        return datetime.min.replace(tzinfo=timezone.utc)
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    else:
        dt = dt.astimezone(timezone.utc)
    return dt

# ---------- 라우트 ----------
@app.get("/healthz")
def healthz():
    return {"ok": True}

@app.get("/", response_class=HTMLResponse)
def home():
    return RedirectResponse("/gov/search")

# ===== 대정부: 직원 검색 (motie_org + moef_org) =====
@app.get("/gov/search", response_class=HTMLResponse)
async def gov_search_page(
    request: Request,
    q: Optional[str] = Query(default=None, description="이름/부서 검색어"),
    src: str = Query(default="all", description="기관: all|MOTIE|MOEF"),
):
    rows: List[Dict[str, Any]] = []
    if q:
        sb = get_supabase()
        q_like = f"%{q}%"
        if src in ("all", "MOTIE", "motie"):
            r = sb.table("motie_org").select("*") \
                .or_(f"name.ilike.{q_like},department.ilike.{q_like}") \
                .limit(200).execute().data or []
            for x in r:
                rows.append({
                    "source": "MOTIE",
                    "department": _to_str(x.get("department")),
                    "position": _to_str(x.get("position")),
                    "name": _to_str(x.get("name")),
                    "phone": _to_str(x.get("phone")),
                    "task": _to_str(x.get("task")),
                })
        if src in ("all", "MOEF", "moef"):
            r = sb.table("moef_org").select("*") \
                .or_(f"name.ilike.{q_like},department.ilike.{q_like}") \
                .limit(200).execute().data or []
            for x in r:
                rows.append({
                    "source": "MOEF",
                    "department": _to_str(x.get("department")),
                    "position": _to_str(x.get("position")),
                    "name": _to_str(x.get("name")),
                    "phone": _to_str(x.get("phone")),
                    "task": _to_str(x.get("task")),
                })

    return templates.TemplateResponse(
        "search.html",
        {
            "request": request,
            "q": q or "",
            "src": src,
            "rows": rows,
        },
    )

# ===== 대정부: 인사동정 타임라인 (motie_id + moef_id) =====
def _as_motie_url(article_id: str) -> str:
    return f"https://www.motie.go.kr/kor/article/ATCL6e90bb9de/{article_id}/view?"

def _as_moef_url(bbs_id: str, post_id: str) -> str:
    return f"https://www.moef.go.kr/nw/notice/hrDetail.do?searchBbsId1={bbs_id}&searchNttId1={post_id}"

@app.get("/gov/timeline", response_class=HTMLResponse)
async def timeline_page(
    request: Request,
    src: str = Query(default="all"),
    page: int = Query(default=1, ge=1),
    page_size: int = Query(default=20, ge=5, le=100),
):
    sb = get_supabase()
    pool: List[Dict[str, Any]] = []

    if src in ("all", "MOTIE", "motie"):
        motie_rows = (
            sb.table("motie_id")
              .select("id,created_at,title,posted_at")
              .order("posted_at", desc=True)
              .limit(500)
              .execute().data or []
        )
        for r in motie_rows:
            item_id = _to_str(r.get("id"))
            pool.append({
                "source": "MOTIE",
                "title": _to_str(r.get("title") or "산업부 인사발령"),
                "tag": None,
                "url": _as_motie_url(item_id) if item_id else "",
                "posted_at": r.get("posted_at"),
                "created_at": r.get("created_at"),
                "_posted_date": _parse_posted(r.get("posted_at")),
                "_created_dt": _parse_created(r.get("created_at")),
            })

    if src in ("all", "MOEF", "moef"):
        moef_rows = (
            sb.table("moef_id")
              .select('id,created_at,"bbsId","postId",title,tag,posted_at')
              .order("posted_at", desc=True)
              .limit(500)
              .execute().data or []
        )
        for r in moef_rows:
            bbs, pid = _to_str(r.get("bbsId")), _to_str(r.get("postId"))
            pool.append({
                "source": "MOEF",
                "title": _to_str(r.get("title") or "기재부 인사발령"),
                "tag": _to_str(r.get("tag") or "") or None,
                "url": _as_moef_url(bbs, pid) if (bbs and pid) else "",
                "posted_at": r.get("posted_at"),
                "created_at": r.get("created_at"),
                "_posted_date": _parse_posted(r.get("posted_at")),
                "_created_dt": _parse_created(r.get("created_at")),
            })

    pool.sort(key=lambda x: (x["_posted_date"], x["_created_dt"]), reverse=True)

    start = (page - 1) * page_size
    end = start + page_size
    rows = [
        {
            "source": it["source"],
            "title": it["title"],
            "tag": it["tag"],
            "url": it["url"],
            "posted_at": it["posted_at"],
            "created_at": it["created_at"],
        }
        for it in pool[start:end]
    ]
    has_more = end < len(pool)

    return templates.TemplateResponse(
        "timeline.html",
        {
            "request": request,
            "src": src,
            "rows": rows,
            "page": page,
            "has_more": has_more,
        },
    )

# ===== 그룹사: 임원 검색 (kepco_org) =====
@app.get("/group/search", response_class=HTMLResponse)
async def group_search_page(
    request: Request,
    q: Optional[str] = Query(default=None, description="이름/부서/직위 검색"),
):
    rows: List[Dict[str, Any]] = []
    if q:
        sb = get_supabase()
        q_like = f"%{q}%"
        r = (
            sb.table("kepco_org")
              .select("*")
              .or_(f"name.ilike.{q_like},department.ilike.{q_like},position.ilike.{q_like}")
              .limit(300)
              .execute().data or []
        )
        for x in r:
            rows.append({
                "department": _to_str(x.get("department")),
                "position": _to_str(x.get("position")),
                "name": _to_str(x.get("name")),
                "gender": _to_str(x.get("gender")),
                "start": _to_str(x.get("start")),
                "end": _to_str(x.get("end")),
                "task": _to_str(x.get("task")),
                "career": _to_str(x.get("career")),
                # PDF는 타임라인에서 연결
            })

    return templates.TemplateResponse(
        "group_search.html",
        {
            "request": request,
            "q": q or "",
            "rows": rows,
        },
    )

# ===== 그룹사: 인사동정 타임라인 (kepco_id) =====
@app.get("/group/timeline", response_class=HTMLResponse)
async def group_timeline_page(
    request: Request,
    page: int = Query(default=1, ge=1),
    page_size: int = Query(default=20, ge=5, le=100),
):
    sb = get_supabase()
    # posted_at 컬럼이 없다면 created_at 기준 정렬
    rows_all = (
        sb.table("kepco_id")
          .select("id,created_at,posted_at,pdf_url,company")
          .order("created_at", desc=True)
          .limit(500)
          .execute().data or []
    )

    # 정렬 (posted_at 우선, 없으면 created_at)
    def _key(x):
        p = _parse_posted(x.get("posted_at"))
        c = _parse_created(x.get("created_at"))
        return (p, c)

    rows_all.sort(key=_key, reverse=True)

    start = (page - 1) * page_size
    end = start + page_size
    page_rows = rows_all[start:end]
    has_more = end < len(rows_all)

    # 화면용 매핑
    rows = []
    for r in page_rows:
        rows.append({
            "company": _to_str(r.get("company") or "-"),
            "posted_at": r.get("posted_at"),
            "created_at": r.get("created_at"),
            "pdf_url": _to_str(r.get("pdf_url") or ""),
            "id": _to_str(r.get("id")),
        })

    return templates.TemplateResponse(
        "group_timeline.html",
        {
            "request": request,
            "rows": rows,
            "page": page,
            "has_more": has_more,
        },
    )

# ===== 기타 업무: 인강 자동 넘기기 =====
@app.get("/tools/auto-lecture", response_class=HTMLResponse)
def tool_auto_lecture(request: Request):
    return templates.TemplateResponse("tools_auto_lecture.html", {"request": request})
