#!/usr/bin/env python3
from __future__ import annotations

import argparse
import shutil
import sys
from http.server import ThreadingHTTPServer
from pathlib import Path
from typing import Any

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

from packages.pet_package_schema import ALLOWED_ACTIONS
from services.api.local_api import LocalPetApi
from services.api.local_server import make_handler
from services.api.local_store import LocalJsonStore

DEFAULT_STATE_DIR = ROOT / "outputs" / "local_api"
ZHOU_LIU_FIXTURE = ROOT / "tests" / "fixtures" / "public" / "周六-合成样例"
YI_NENG_JING_FIXTURE = ROOT / "tests" / "fixtures" / "public" / "一能静-合成样例"


def create_local_api(*, state_dir: Path = DEFAULT_STATE_DIR) -> LocalPetApi:
    state_dir.mkdir(parents=True, exist_ok=True)
    return LocalPetApi(
        store=LocalJsonStore(state_dir / "local-api-store.json"),
        build_runner=public_demo_build_runner,
        output_root=state_dir / "pet_builds",
    )


def make_local_handler(*, api: LocalPetApi, web_root: Path = ROOT):
    return make_handler(api=api, web_root=web_root)


def main() -> int:
    parser = argparse.ArgumentParser(description="Serve the local AI desktop pet test app.")
    parser.add_argument("--host", default="127.0.0.1")
    parser.add_argument("--port", type=int, default=8765)
    parser.add_argument("--state-dir", type=Path, default=DEFAULT_STATE_DIR)
    args = parser.parse_args()

    api = create_local_api(state_dir=args.state_dir)
    server = ThreadingHTTPServer((args.host, args.port), make_local_handler(api=api, web_root=ROOT))
    print(f"Serving AI desktop pet test app at http://{args.host}:{args.port}/apps/web/index.html")
    print(f"Serving local staging API at http://{args.host}:{args.port}/api")
    server.serve_forever()
    return 0


def public_demo_build_runner(*, build: dict[str, Any], pet: dict[str, Any], media: list[dict[str, Any]], output_root: Path) -> dict[str, Any]:
    fixture = _select_public_fixture(pet=pet, media=media)
    build_dir = output_root / str(build["build_id"])
    package_dir = build_dir / "package"
    qa_dir = build_dir / "qa"
    if build_dir.exists():
        shutil.rmtree(build_dir)
    package_dir.mkdir(parents=True)
    qa_dir.mkdir(parents=True)

    for filename in ("pet.json", "spritesheet.webp", "spritesheet.png"):
        source = fixture / filename
        if source.exists():
            shutil.copy2(source, package_dir / filename)
    contact_sheet = qa_dir / "contact-sheet.html"
    contact_sheet.write_text(
        _demo_contact_sheet(display_name=str(pet.get("pet_name") or "pet"), spritesheet="../package/spritesheet.webp"),
        encoding="utf-8",
    )
    return {
        "build_dir": build_dir,
        "package_ref": "package/pet.json",
        "preview_ref": "qa/contact-sheet.html",
        "actions": list(ALLOWED_ACTIONS),
        "checksum_valid": True,
        "runtime_compatible": True,
    }


def _select_public_fixture(*, pet: dict[str, Any], media: list[dict[str, Any]]) -> Path:
    haystack = " ".join(
        [
            str(pet.get("pet_name") or ""),
            *[str(item.get("storage_ref") or "") for item in media],
            *[str(item.get("original_filename") or "") for item in media],
        ]
    ).lower()
    if "yinengjing" in haystack or "一能静" in haystack or "mimi" in haystack:
        return YI_NENG_JING_FIXTURE
    return ZHOU_LIU_FIXTURE


def _demo_contact_sheet(*, display_name: str, spritesheet: str) -> str:
    rows = "".join(f"<li>{action}</li>" for action in ALLOWED_ACTIONS)
    return f"""<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8" />
<title>{display_name} local preview</title>
<body>
  <h1>{display_name} 本地预览</h1>
  <p>公开演示素材，仅用于本地 API 闭环验证。</p>
  <img src="{spritesheet}" alt="{display_name} spritesheet preview" />
  <ul>{rows}</ul>
</body>
</html>
"""


if __name__ == "__main__":
    raise SystemExit(main())
