# /var/www/html/bot/app/web/pages/index.py
from __future__ import annotations
from datetime import date, datetime, timedelta, timezone
import json
from typing import Dict, List, Optional
from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse

from app.web.deps import (
    templates, sb,
    _today_items_from, _ping_status, _count_last_24h,
)

router = APIRouter()
KST = timezone(timedelta(hours=9))

def _yyyymmdd(d: date) -> str:
    return d.strftime("%Y-%m-%d")

def _mmdd(d: date) -> str:
    return d.strftime("%m-%d")

def _to_kst_str(dt_iso: Optional[str]) -> Optional[str]:
    """ISO8601 문자열(UTC/오프셋 포함)을 KST 'YYYY-MM-DD HH:MM'로."""
    if not dt_iso:
        return None
    try:
        dt = datetime.fromisoformat(str(dt_iso).replace("Z", "+00:00"))
        return dt.astimezone(KST).strftime("%Y-%m-%d %H:%M")
    except Exception:
        return str(dt_iso)

async def _counts_last_n_days(table: str, days: int = 7) -> Dict[str, int]:
    """테이블에서 최근 N일(created_at 기준) 일자별 건수를 dict[YYYY-MM-DD]=count 로 반환"""
    start = date.today() - timedelta(days=days-1)
    start_iso = f"{_yyyymmdd(start)}T00:00:00"
    try:
        res = (
            sb.table(table)
              .select("created_at")
              .gte("created_at", start_iso)
              .limit(20000)
              .execute()
        )
        rows = res.data or []
    except Exception:
        rows = []
    buckets: Dict[str, int] = {}
    for r in rows:
        ts = r.get("created_at")
        if not ts:
            continue
        key = str(ts)[:10]
        buckets[key] = buckets.get(key, 0) + 1
    return buckets

def _series_fill(buckets: Dict[str,int], days: int = 7) -> Dict[str, List]:
    """연속된 N일 라벨과 해당 카운트(없으면 0)를 반환"""
    labels, counts = [], []
    start = date.today() - timedelta(days=days-1)
    for i in range(days):
        d = start + timedelta(days=i)
        ymd = _yyyymmdd(d)
        labels.append(_mmdd(d))
        counts.append(buckets.get(ymd, 0))
    return {"labels": labels, "counts": counts}

def _last_run_finished_at(target: str) -> Optional[str]:
    """crawler_run에서 status='passed'이면서 finished_at 최근 1건 반환"""
    try:
        res = (
            sb.table("crawler_run")
              .select("finished_at")
              .eq("target", target)
              .eq("status", "passed")
              .not_.is_("finished_at", "null")
              .order("finished_at", desc=True)
              .limit(1)
              .execute()
        )
        rows = res.data or []
        return rows[0]["finished_at"] if rows else None
    except Exception:
        return None

@router.get("/", response_class=HTMLResponse)
async def index(request: Request, window: int = Query(default=7, description="차트 기간(7/30)")):
    """홈 대시보드: 오늘자 스냅샷 + 상태 + 7일 추이"""
    window = 30 if window == 30 else 7
    # 정부 부처 오늘자 아이템
    moef_today = _today_items_from("moef_id", "MOEF", title_key="title", url_key="url", tag_key="tag")
    motie_today = _today_items_from("motie_id", "MOTIE", title_key="title", url_key="url", tag_key=None)
    me_today = _today_items_from("me_id", "ME", title_key="title", url_key="url", tag_key=None)
    gov_today = moef_today + motie_today + me_today

    # ALIO(한전 그룹) 오늘자
    try:
        res_k = (
            sb.table("kepco_id")
              .select("department,posted_at,pdf_url,created_at")
              .order("id", desc=True)
              .limit(200)
              .execute()
        )
        k_rows = res_k.data or []
    except Exception:
        k_rows = []

    group_today: List[dict] = []
    today_str = date.today().isoformat()
    for r in k_rows:
        d = str(r.get("posted_at") or r.get("created_at") or "")[:10]
        if d == today_str:
            group_today.append({
                "department": (r.get("department") or "-"),
                "url": r.get("pdf_url"),
                "date": d,
            })

    # 사이트 상태/최근 24시간 수집건
    status = {
        "MOEF": {
            "ping": _ping_status("https://www.moef.go.kr"),
            "count24": _count_last_24h("moef_id"),
        },
        "MOTIE": {
            "ping": _ping_status("https://www.motie.go.kr"),
            "count24": _count_last_24h("motie_id"),
        },
        "ME": {
            "ping": _ping_status("https://me.go.kr"),
            "count24": _count_last_24h("me_org_snapshot"),
        },
        "CONGRESS": {
            "ping": _ping_status("https://www.assembly.go.kr"),
            "count24": _count_last_24h("congress_member"),
        },
        "ALIO": {
            "ping": _ping_status("https://www.alio.go.kr"),
            "count24": _count_last_24h("kepco_id"),
        },
    }

    # 마지막 갱신(파이프라인 별 최근 passed finished_at)
    last = {
        "MOEF": {
            "insadongjeong": _to_kst_str(_last_run_finished_at("moef_id")),   # 인사동정
            "jikwon":        _to_kst_str(_last_run_finished_at("moef_org")),  # 직원정보
        },
        "MOTIE": {
            "insadongjeong": _to_kst_str(_last_run_finished_at("motie_id")),
            "jikwon":        _to_kst_str(_last_run_finished_at("motie_org")),
        },
        "ME": {
            "insadongjeong": _to_kst_str(_last_run_finished_at("me_id")),
            "jikwon":        _to_kst_str(_last_run_finished_at("me_org")),
        },
        "CONGRESS": {
            "uieon": _to_kst_str(_last_run_finished_at("congress_member")),   # 의원정보
        },
        "ALIO": {
            "gongsi": _to_kst_str(_last_run_finished_at("group_n8n")),        # 공시정보
        },
    }

    # === 기간별 추이 (7/30/90) ===
    moef_b = await _counts_last_n_days("moef_id", days=window)
    motie_b = await _counts_last_n_days("motie_id", days=window)
    alio_b  = await _counts_last_n_days("kepco_id", days=window)

    # 정부(= moef + motie) 합산 버킷
    gov_b: Dict[str,int] = {}
    start = date.today() - timedelta(days=window-1)
    daysN = [start + timedelta(days=i) for i in range(window)]
    for d in daysN:
        ymd = _yyyymmdd(d)
        gov_b[ymd] = (moef_b.get(ymd, 0) + motie_b.get(ymd, 0))

    chart_gov   = _series_fill(gov_b, days=window)
    chart_group = _series_fill(alio_b, days=window)

    return templates.TemplateResponse(
        "index.html",
        {
            "request": request,
            "gov_today": gov_today,
            "group_today": group_today,
            "status": status,
            "last": last,

            "chart_gov": chart_gov,
            "chart_group": chart_group,
            "chart_gov_json": json.dumps(chart_gov, ensure_ascii=False),
            "chart_group_json": json.dumps(chart_group, ensure_ascii=False),
            "window": window,
        },
    )
