from __future__ import annotations

import json
import sys
import threading
import urllib.request
from pathlib import Path

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

from Analyze8780.analyze8780_repository import AnalyzeRepository
from Analyze8780.analyze8780_main import build_server
from Shared.storage.sort_storage import record_downloaded_file


def request_json(url: str, *, method: str = "GET", payload: dict | None = None) -> dict:
    body = json.dumps(payload).encode("utf-8") if payload is not None else None
    req = urllib.request.Request(url, data=body, method=method)
    if body is not None:
        req.add_header("Content-Type", "application/json")
    with urllib.request.urlopen(req, timeout=5) as response:
        return json.loads(response.read().decode("utf-8"))


def test_repository_and_http_api(tmp_path: Path) -> None:
    st_root = tmp_path / "_St"
    st_root.mkdir()
    db_path = st_root / "Shared" / "data" / "sort_local.sqlite3"
    repo = AnalyzeRepository(st_root, db_path)
    a = repo.save_observation({
        "username": "alpha", "shortcode": "A1", "views": 100, "likes": 10,
        "post_url": "https://www.instagram.com/explore/",
        "video_url": "https://cdn.example/A1.mp4",
        "observed_at": "2026-07-19T09:02:00Z",
    })
    repo.save_observation({
        "username": "alpha", "shortcode": "A1", "views": 160, "likes": 14,
        "observed_at": "2026-07-19T09:12:00Z",
    })
    assert repo.accounts()["total"] == 1
    assert repo.account_posts(a["account_id"], sort_by="views_delta")["items"][0]["views_delta"] == 60
    media_dir = tmp_path / "_StDown" / "instagram" / "alpha"
    media_dir.mkdir(parents=True)
    media_file = media_dir / "179_original.mp4"
    media_file.write_bytes(b"video")
    record_downloaded_file(
        st_root=st_root, file_path=media_file, source_mode="MANUAL_SINGLE",
        shortcode="A1", owner_username="alpha", asset_kind="VIDEO",
        account_path="alpha", event_uuid="analyze-original-file",
        file_size=media_file.stat().st_size,
    )

    server = build_server(st_root, db_path, "127.0.0.1", 0)
    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()
    host, port = server.server_address
    base = f"http://{host}:{port}"
    try:
        health = request_json(base + "/api/health")
        assert health["ok"] is True and health["service"] == "Analyze8780"
        assert health["version"] == "2.3.8.232"
        accounts = request_json(base + "/api/accounts?page=1&page_size=50")
        assert accounts["total"] == 1
        queue_saved = request_json(base + "/api/collection-accounts", method="PUT", payload={
            "items": [
                {"username": "alpha", "position": 1},
                {"username": "https://www.instagram.com/explore/", "position": 2},
                {"username": "beta", "position": 3},
            ]
        })
        assert queue_saved["ok"] is True and queue_saved["total"] == 2
        queue_loaded = request_json(base + "/api/collection-accounts")
        assert [item["username"] for item in queue_loaded["items"]] == ["alpha", "beta"]

        posts = request_json(base + f"/api/accounts/{a['account_id']}/posts?sort_by=views_delta")
        assert posts["items"][0]["views_per_hour"] == 360
        assert posts["items"][0]["post_url"] == "https://www.instagram.com/reel/A1/"
        assert posts["items"][0]["folder_name"] == "alpha"
        assert posts["items"][0]["file_name"] == "179_original.mp4"
        deleted = request_json(base + f"/api/accounts/{a['account_id']}", method="DELETE")
        assert deleted["deleted"] is True
        tombstones = request_json(base + "/api/deleted/accounts")
        assert tombstones["items"][0]["username"] == "alpha"
    finally:
        server.shutdown()
        server.server_close()
        thread.join(timeout=5)


def test_runner_uses_py312() -> None:
    runner = (Path(__file__).resolve().parent / "run_Analyze8780.bat").read_text(encoding="utf-8")
    assert "call py312 analyze8780_main.py --host 127.0.0.1 --port 8780" in runner


def test_web_shows_saved_folder_and_original_filename() -> None:
    html = (Path(__file__).resolve().parent / "web" / "index.html").read_text(encoding="utf-8")
    assert "저장 폴더" in html
    assert "원본 파일" in html
    assert "p.folder_name" in html and "p.file_name" in html
