#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""IndexNow 지원 검색엔진에 웹진 기사 URL 수집 요청을 전송한다.

Google 색인 여부는 일반 콘텐츠에 Indexing API를 사용하지 않고
Search Console URL Inspection 연동 결과를 별도로 저장하도록 분리한다.
"""

import argparse
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parents[1]
if str(BASE_DIR) not in sys.path:
    sys.path.insert(0, str(BASE_DIR))

from db import get_conn

INDEXNOW_ENDPOINT = "https://api.indexnow.org/indexnow"


def absolute_url(base_url: str, value: str) -> str:
    value = str(value or "").strip()
    if value.startswith(("http://", "https://")):
        return value
    return urllib.parse.urljoin(base_url.rstrip("/") + "/", value.lstrip("/"))


def load_jobs(conn, limit: int):
    with conn.cursor() as cur:
        cur.execute(
            """SELECT id,article_id,search_engine,article_url,retry_count
                 FROM multi_search_submission_jobs
                WHERE search_engine IN ('naver','bing')
                  AND queue_status IN ('pending','retry_wait')
                ORDER BY updated_at ASC,id ASC
                LIMIT %s""",
            (limit,),
        )
        return list(cur.fetchall() or [])


def update_jobs(conn, ids, status: str, error: str | None = None, retry: bool = False):
    if not ids:
        return
    placeholders = ",".join(["%s"] * len(ids))
    retry_sql = ",retry_count=retry_count+1" if retry else ""
    with conn.cursor() as cur:
        cur.execute(
            f"""UPDATE multi_search_submission_jobs
                   SET queue_status=%s,error_message=%s,updated_at=NOW(){retry_sql}
                 WHERE id IN ({placeholders})""",
            [status, (error or None)] + list(ids),
        )
    conn.commit()


def submit_indexnow(host: str, key: str, key_location: str, urls: list[str], timeout: int):
    payload = {"host": host, "key": key, "keyLocation": key_location, "urlList": urls}
    request = urllib.request.Request(
        INDEXNOW_ENDPOINT,
        data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
        headers={"Content-Type": "application/json; charset=utf-8", "User-Agent": "HongheeWebzine/1.0"},
        method="POST",
    )
    with urllib.request.urlopen(request, timeout=timeout) as response:
        return int(response.status), response.read(1000).decode("utf-8", errors="replace")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--limit", type=int, default=100)
    parser.add_argument("--timeout", type=int, default=25)
    args = parser.parse_args()

    base_url = os.getenv("MULTI_WEBZINE_BASE_URL", "http://multi.hongheemarketing.com").strip().rstrip("/")
    parsed = urllib.parse.urlparse(base_url)
    host = parsed.netloc
    key = os.getenv("MULTI_INDEXNOW_KEY", "").strip()
    key_location = os.getenv("MULTI_INDEXNOW_KEY_LOCATION", "").strip() or f"{base_url}/{key}.txt"
    if not host:
        raise RuntimeError("MULTI_WEBZINE_BASE_URL의 호스트를 확인할 수 없습니다.")
    if not key:
        print("[SEARCH SUBMIT SKIP] MULTI_INDEXNOW_KEY가 없어 대기중 작업을 유지합니다.")
        return

    conn = get_conn()
    try:
        jobs = load_jobs(conn, max(1, min(args.limit, 10000)))
        if not jobs:
            print("[SEARCH SUBMIT] pending=0")
            return
        ids = [int(row["id"]) for row in jobs]
        urls = list(dict.fromkeys(absolute_url(base_url, row["article_url"]) for row in jobs))
        update_jobs(conn, ids, "processing")
        try:
            status, body = submit_indexnow(host, key, key_location, urls, args.timeout)
            if status not in (200, 202):
                raise RuntimeError(f"IndexNow HTTP {status}: {body[:300]}")
            update_jobs(conn, ids, "submitted")
            print(f"[SEARCH SUBMIT OK] jobs={len(ids)} urls={len(urls)} http={status}")
        except (urllib.error.URLError, TimeoutError, RuntimeError) as exc:
            max_retry = max(int(row.get("retry_count") or 0) for row in jobs) + 1
            next_status = "failed" if max_retry >= 3 else "retry_wait"
            update_jobs(conn, ids, next_status, str(exc)[:1000], retry=True)
            print(f"[SEARCH SUBMIT ERROR] jobs={len(ids)} status={next_status} error={exc}")
            raise
    finally:
        conn.close()


if __name__ == "__main__":
    main()
