from __future__ import annotations

import json
import os
import subprocess
import sys
import threading
from collections.abc import Generator
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path

import pytest

pytestmark = pytest.mark.integration


def _source_env(repo_root: Path) -> dict[str, str]:
    env = dict(os.environ)
    src_path = str(repo_root / "src")
    existing = env.get("PYTHONPATH")
    env["PYTHONPATH"] = src_path if not existing else f"{src_path}{os.pathsep}{existing}"
    return env


class _CliSiteHandler(BaseHTTPRequestHandler):
    def do_GET(self) -> None:  # noqa: N802 - BaseHTTPRequestHandler signature
        body = (
            "<html><head><title>CLI Smoke</title></head>"
            "<body><h1>CLI integration</h1><p id='content'>ok</p></body></html>"
        )
        self.send_response(200)
        self.send_header("Content-Type", "text/html; charset=utf-8")
        self.end_headers()
        self.wfile.write(body.encode("utf-8"))

    def log_message(self, format: str, *args: object) -> None:  # noqa: A003
        return


@pytest.fixture(scope="module")
def cli_site() -> Generator[str, None, None]:
    server = HTTPServer(("127.0.0.1", 0), _CliSiteHandler)
    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()
    base = f"http://127.0.0.1:{server.server_address[1]}"
    try:
        yield base
    finally:
        server.shutdown()
        thread.join()


def test_python_m_screenshot_cli_help() -> None:
    repo_root = Path(__file__).resolve().parents[1]

    proc = subprocess.run(
        [sys.executable, "-m", "screenshot.cli", "--help"],
        cwd=repo_root,
        env=_source_env(repo_root),
        capture_output=True,
        text=True,
        check=False,
    )

    assert proc.returncode == 0
    assert "Generic screenshot capture utilities" in proc.stdout
    assert "local" in proc.stdout


def test_python_m_screenshot_cli_local_disabled_job(tmp_path: Path) -> None:
    repo_root = Path(__file__).resolve().parents[1]
    input_path = tmp_path / "jobs.jsonl"
    output_dir = tmp_path / "output"
    summary_path = tmp_path / "summary.json"
    input_path.write_text(
        json.dumps(
            {
                "job_id": "disabled-job",
                "url": "https://example.com",
                "options": {
                    "schema_version": "screenshot_options/v2",
                    "capture": {"enabled": False},
                },
            }
        )
        + "\n",
        encoding="utf-8",
    )

    proc = subprocess.run(
        [
            sys.executable,
            "-m",
            "screenshot.cli",
            "local",
            "--input",
            str(input_path),
            "--output-dir",
            str(output_dir),
            "--summary-file",
            str(summary_path),
        ],
        cwd=repo_root,
        env=_source_env(repo_root),
        capture_output=True,
        text=True,
        check=False,
    )

    assert proc.returncode == 0
    assert summary_path.exists()
    payload = json.loads(summary_path.read_text(encoding="utf-8"))
    assert payload["success_count"] == 0
    assert payload["failure_count"] == 0
    assert payload["partial_count"] == 0
    assert payload["skipped_count"] == 1
    assert payload["results"][0]["job_id"] == "disabled-job"
    assert payload["results"][0]["outcome"] == "skipped"


def test_python_m_screenshot_cli_local_captures_site(tmp_path: Path, cli_site: str) -> None:
    repo_root = Path(__file__).resolve().parents[1]
    input_path = tmp_path / "jobs.jsonl"
    output_dir = tmp_path / "output"
    summary_path = tmp_path / "summary.json"
    input_path.write_text(
        json.dumps(
            {
                "job_id": "browser-job",
                "url": f"{cli_site}/",
                "options": {
                    "schema_version": "screenshot_options/v2",
                    "capture": {
                        "enabled": True,
                        "max_pages": 1,
                        "depth": 0,
                        "viewports": ["desktop"],
                        "post_nav_wait_s": 0.1,
                        "timeout_s": 20.0,
                        "max_capture_attempts": 1,
                    },
                },
            }
        )
        + "\n",
        encoding="utf-8",
    )

    proc = subprocess.run(
        [
            sys.executable,
            "-m",
            "screenshot.cli",
            "local",
            "--input",
            str(input_path),
            "--output-dir",
            str(output_dir),
            "--summary-file",
            str(summary_path),
            "--backend",
            "playwright",
        ],
        cwd=repo_root,
        env=_source_env(repo_root),
        capture_output=True,
        text=True,
        check=False,
    )

    assert proc.returncode == 0, proc.stderr
    payload = json.loads(summary_path.read_text(encoding="utf-8"))
    assert payload["success_count"] == 1
    assert payload["failure_count"] == 0
    assert payload["results"][0]["outcome"] == "success"

    metadata_path = Path(payload["results"][0]["metadata_path"])
    assert metadata_path.exists()
    metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
    entries = metadata.get("entries", [])
    assert entries

    site_root = metadata_path.parent.parent
    screenshot_paths: list[Path] = []
    for entry in entries:
        if not isinstance(entry, dict):
            continue
        rel_path = entry.get("screenshot_path")
        status = entry.get("status")
        if not rel_path or status not in {"captured", "success"}:
            continue
        candidate = Path(str(rel_path))
        if not candidate.is_absolute():
            candidate = site_root / candidate
        screenshot_paths.append(candidate)

    assert screenshot_paths
    for screenshot_path in screenshot_paths:
        assert screenshot_path.exists()
