#!/usr/bin/env python3
import argparse
import datetime as dt
import html
import json
import re
import sys
from typing import List, Dict, Any

import requests

LH_URL = "https://k-skill-proxy.nomadamas.org/v1/lh-notice/search"
SH_URL = "https://www.i-sh.co.kr/app/lay2/program/S1T294C297/www/brd/m_247/list.do"
SH_DETAIL_BASE = "https://www.i-sh.co.kr/app/lay2/program/S1T294C297/www/brd/m_247/view.do?multi_itm_seq=2&seq="


def fetch_lh(keyword: str, region: str, status: str, limit: int) -> List[Dict[str, Any]]:
    params = {"pageSize": limit}
    if keyword:
        params["keyword"] = keyword
    if region:
        params["region"] = region
    if status:
        params["status"] = status

    r = requests.get(LH_URL, params=params, timeout=20)
    r.raise_for_status()
    data = r.json()
    return data.get("items", [])[:limit]


def fetch_sh(keyword: str, page: int, limit: int) -> List[Dict[str, Any]]:
    params = {"multi_itm_seq": "2", "page": str(page)}
    if keyword:
        params["srchWord"] = keyword
        params["srchTp"] = "0"

    text = requests.get(SH_URL, params=params, timeout=20).text

    pat = re.compile(r"getDetailView\('(?P<seq>\d+)'\).*?</a>", re.S)
    title_pat = re.compile(r">\s*([^<>]+?)\s*</a>\s*$", re.S)

    items: List[Dict[str, Any]] = []
    seen = set()
    for m in pat.finditer(text):
        seq = m.group("seq")
        block = m.group(0)
        t = title_pat.search(block)
        if not t:
            continue
        title = html.unescape(re.sub(r"\s+", " ", t.group(1))).strip()
        if not title or seq in seen:
            continue
        seen.add(seq)
        items.append({"seq": seq, "title": title, "detail_url": SH_DETAIL_BASE + seq})
        if len(items) >= limit:
            break

    return items


def build_payload(args: argparse.Namespace) -> Dict[str, Any]:
    now = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    payload: Dict[str, Any] = {
        "generated_at": now,
        "query": {
            "keyword": args.keyword,
            "lh_region": args.region,
            "lh_status": args.status,
            "limit": args.limit,
            "sh_page": args.page,
        },
        "sources": {"lh": {"ok": True, "count": 0, "items": [], "error": None}, "sh": {"ok": True, "count": 0, "items": [], "error": None}},
    }

    try:
        lh_items = fetch_lh(args.keyword, args.region, args.status, args.limit)
        payload["sources"]["lh"]["items"] = lh_items
        payload["sources"]["lh"]["count"] = len(lh_items)
    except Exception as e:
        payload["sources"]["lh"]["ok"] = False
        payload["sources"]["lh"]["error"] = str(e)

    try:
        sh_items = fetch_sh(args.keyword, args.page, args.limit)
        payload["sources"]["sh"]["items"] = sh_items
        payload["sources"]["sh"]["count"] = len(sh_items)
    except Exception as e:
        payload["sources"]["sh"]["ok"] = False
        payload["sources"]["sh"]["error"] = str(e)

    return payload


def print_text(payload: Dict[str, Any]) -> None:
    q = payload["query"]
    print(f"\n[통합 청약 브리핑] {payload['generated_at']}")
    print(f"키워드={q['keyword']} | LH(region={q['lh_region']}, status={q['lh_status']}) | SH(page={q['sh_page']})\n")

    lh = payload["sources"]["lh"]
    if not lh["ok"]:
        print(f"[LH] 조회 실패: {lh['error']}")
    print(f"[LH] {lh['count']}건")
    for i, it in enumerate(lh["items"], 1):
        print(f"{i}. {it.get('pan_nm','(제목없음)')} | {it.get('cnp_cd_nm','-')} | {it.get('pan_ss','-')} | 마감:{it.get('clsg_dt','-')}\n   {it.get('detail_url','')}")

    sh = payload["sources"]["sh"]
    if not sh["ok"]:
        print(f"\n[SH] 조회 실패: {sh['error']}")
    print(f"\n[SH] {sh['count']}건")
    for i, it in enumerate(sh["items"], 1):
        print(f"{i}. {it['title']}\n   {it['detail_url']}")


def main() -> int:
    p = argparse.ArgumentParser(description="LH/SH 청약 공고 통합 요약")
    p.add_argument("--keyword", default="행복주택", help="검색 키워드")
    p.add_argument("--region", default="서울특별시", help="LH 지역 필터")
    p.add_argument("--status", default="공고중", help="LH 상태 필터")
    p.add_argument("--limit", type=int, default=5, help="소스별 최대 결과")
    p.add_argument("--page", type=int, default=1, help="SH 페이지")
    p.add_argument("--json", action="store_true", dest="as_json", help="JSON 형식으로 출력")
    args = p.parse_args()

    payload = build_payload(args)

    if args.as_json:
        print(json.dumps(payload, ensure_ascii=False, indent=2))
    else:
        print_text(payload)

    return 0


if __name__ == "__main__":
    sys.exit(main())
