from __future__ import annotations

import re
from pathlib import Path

import pytest

import screenshot
from screenshot import ScreenshotCaptureResult
from screenshot._models_options import BrowserCompatOptions, CaptureOptions
from screenshot._shared.errors import make_error

README_PATH = Path(__file__).resolve().parents[1] / "README.md"


def _readme_text() -> str:
    return README_PATH.read_text(encoding="utf-8")


def _extract_python_api_block() -> str:
    text = _readme_text()
    match = re.search(
        r"### Python API: Programmatic Usage.*?```python\n(.*?)```",
        text,
        flags=re.DOTALL,
    )
    if match is None:
        raise AssertionError("README Python API example block not found")
    return match.group(1)


def _readme_option_default(option: str) -> str:
    pattern = rf"^\| `{re.escape(option)}` \| .*? \| `([^`]+)` \|$"
    match = re.search(pattern, _readme_text(), flags=re.MULTILINE)
    if match is None:
        raise AssertionError(f"README option row for {option} not found")
    return match.group(1)


def test_readme_common_option_defaults_match_runtime_models() -> None:
    capture_defaults = CaptureOptions(enabled=True)
    browser_defaults = BrowserCompatOptions()

    assert _readme_option_default("--depth") == str(capture_defaults.depth)
    assert _readme_option_default("--max-pages") == str(capture_defaults.max_pages)
    assert _readme_option_default("--scroll") == str(capture_defaults.scroll).lower()
    assert _readme_option_default("--full-page") == str(capture_defaults.full_page).lower()
    assert _readme_option_default("--timeout-s") == str(int(capture_defaults.timeout_s))
    assert _readme_option_default("--post-nav-wait-s") == str(capture_defaults.post_nav_wait_s)
    assert _readme_option_default("--pre-capture-wait-s") == str(
        capture_defaults.pre_capture_wait_s
    )
    assert _readme_option_default("--max-viewport-concurrency") == str(
        capture_defaults.max_viewport_concurrency
    )
    assert _readme_option_default("--hide-overlays") == str(browser_defaults.hide_overlays).lower()
    assert (
        _readme_option_default("--disable-animations")
        == str(browser_defaults.disable_animations).lower()
    )
    assert (
        _readme_option_default("--allow-autoplay") == str(browser_defaults.allow_autoplay).lower()
    )
    assert _readme_option_default("--mute-media") == str(browser_defaults.mute_media).lower()
    assert _readme_option_default("--block-media") == str(browser_defaults.block_media).lower()


def test_readme_python_api_example_uses_outcome_contract() -> None:
    block = _extract_python_api_block()

    assert "ScreenshotCaptureOutcome.SUCCESS" in block
    assert "ScreenshotCaptureOutcome.PARTIAL" in block
    assert "result.succeeded" not in block
    assert 'result.outcome == "success"' not in block


def test_readme_python_api_example_executes_with_stubbed_runner(
    monkeypatch: pytest.MonkeyPatch, tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
    code = _extract_python_api_block()

    async def fake_capture(*_args: object, **_kwargs: object) -> ScreenshotCaptureResult:
        return ScreenshotCaptureResult(
            requested=1,
            captured=1,
            failed=1,
            metadata_path=None,
            entries=[],
            errors=[make_error("timeout", "timed out after capture")],
            job_id="readme-demo",
        )

    monkeypatch.setattr(screenshot, "capture_screenshots_async", fake_capture)
    monkeypatch.chdir(tmp_path)

    namespace = {"__name__": "__main__"}
    exec(compile(code, str(README_PATH), "exec"), namespace)

    output = capsys.readouterr().out
    assert "Partially captured 1 screenshot(s)" in output
    assert "Partial failure: timed out after capture" in output
