# -*- coding: utf-8 -*-
"""ig_sort.py — Instagram sort/server sync worker helper.

역할:
- yjm_win2rtc 안에서 서버/yellow.php/MySQL 연동만 담당한다.
- 마우스 클릭, hover 판단, md5 계산, UI 조작은 하지 않는다.
- test.py 레거시 진단 파일에서 API 호출 기능만 추출한 모듈이다.
"""

from __future__ import annotations

import json
import os
import socket
import urllib.parse
import urllib.request
from typing import Any, Callable

DEFAULT_BASE_URL = "https://n.yjm.kr/i/yellow.php"
DEFAULT_TOKEN = "ABC1234XYZ"

LogFn = Callable[[str], None]


def default_user() -> str:
    return (os.environ.get("COMPUTERNAME") or socket.gethostname() or "local_pc").strip() or "local_pc"


def mask_secret(value: Any) -> str:
    s = str(value or "")
    if len(s) <= 8:
        return "****" if s else ""
    return s[:4] + "..." + s[-3:]


def _api_cfg(cfg: dict[str, Any] | None) -> dict[str, Any]:
    cfg = cfg if isinstance(cfg, dict) else {}
    api = cfg.get("yellow_api") if isinstance(cfg.get("yellow_api"), dict) else {}
    return {
        "enabled": bool(api.get("enabled", True)),
        "url": str(api.get("url") or DEFAULT_BASE_URL).strip(),
        "token": str(api.get("token") or DEFAULT_TOKEN).strip(),
        "timeout_sec": float(api.get("timeout_sec") or 10),
    }


def call_api(cfg: dict[str, Any] | None, mode: str, fields: dict[str, Any] | None = None, logger: LogFn | None = None) -> dict[str, Any]:
    """Call yellow.php.

    반환은 항상 dict. 네트워크 실패는 예외를 던지지 않고 ok=False로 반환한다.
    """
    logger = logger or (lambda msg: None)
    api = _api_cfg(cfg)
    if not api.get("enabled", True):
        logger(f"ig_sort: 서버 전송 꺼짐 mode={mode}")
        return {"ok": False, "skipped": True, "error": "yellow_api_disabled", "mode": mode}
    url = str(api.get("url") or "").strip()
    token = str(api.get("token") or "").strip()
    if not url:
        logger(f"ig_sort: 서버 URL 없음 mode={mode}")
        return {"ok": False, "error": "yellow_api_url_empty", "mode": mode}

    payload = {"mode": str(mode or ""), "token": token}
    payload.update({k: v for k, v in (fields or {}).items() if v is not None})
    log_payload = dict(payload)
    if "token" in log_payload:
        log_payload["token"] = mask_secret(log_payload.get("token"))

    body = urllib.parse.urlencode(payload).encode("utf-8")
    req = urllib.request.Request(
        url,
        data=body,
        headers={"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"},
        method="POST",
    )
    try:
        logger(f"ig_sort: 서버 요청 mode={mode} shortcode={payload.get('shortcode','')} asset={payload.get('asset_kind','')}")
        with urllib.request.urlopen(req, timeout=float(api.get("timeout_sec") or 10)) as res:
            raw = res.read().decode("utf-8", errors="replace")
            try:
                parsed = json.loads(raw)
            except Exception:
                parsed = {"ok": False, "raw": raw, "error": "bad_json_from_yellow"}
            parsed["http_status"] = getattr(res, "status", None)
            logger(
                "ig_sort: 서버 응답 "
                f"mode={mode} ok={parsed.get('ok')} exists={parsed.get('exists','')} error={parsed.get('error','')}"
            )
            return parsed if isinstance(parsed, dict) else {"ok": False, "error": "bad_response", "mode": mode}
    except Exception as e:
        logger(f"ig_sort: 서버 실패 mode={mode} error={e}")
        return {"ok": False, "error": str(e), "error_code": "yellow_api_error", "mode": mode}


__all__ = ["call_api", "default_user", "mask_secret", "DEFAULT_BASE_URL", "DEFAULT_TOKEN"]
