"""Contract tests for WebViewController dual-protocol support."""

from __future__ import annotations

from typing import Any

import pytest

from nomo_e2e.controller import WebViewController
from nomo_e2e.exceptions import WebViewOperationError


class FakeAdapter:
    def __init__(self, endpoint: str) -> None:
        self.endpoint = endpoint
        self.connected = False

    def connect(self) -> None:
        self.connected = True

    def disconnect(self) -> None:
        self.connected = False

    def click(self, selector: str, timeout_ms: int = 30000) -> None:
        return None

    def type_text(self, selector: str, text: str, timeout_ms: int = 30000) -> None:
        return None

    def get_text(self, selector: str, timeout_ms: int = 30000) -> str:
        return "ok"

    def get_attribute(self, selector: str, attr: str, timeout_ms: int = 30000) -> str:
        return "value"

    def screenshot(self, path: str, selector: str | None = None, timeout_ms: int = 30000) -> bytes:
        return b"img"

    def execute_script(self, script: str, *args: Any) -> Any:
        if "readyState" in script:
            return "complete"
        if "title" in script:
            return "title"
        return None

    def wait_for_selector(self, selector: str, timeout_ms: int = 30000) -> bool:
        return True

    @property
    def url(self) -> str:
        return "http://example.com"

    @property
    def title(self) -> str:
        return "Test Page"


class TestControllerDriverResolution:
    def test_resolve_auto_returns_webdriver(self) -> None:
        result = WebViewController._resolve_driver("auto")
        assert result == "webdriver"

    def test_resolve_cdp_returns_cdp(self) -> None:
        result = WebViewController._resolve_driver("cdp")
        assert result == "cdp"

    def test_resolve_webdriver_returns_webdriver(self) -> None:
        result = WebViewController._resolve_driver("webdriver")
        assert result == "webdriver"

    def test_resolve_case_insensitive(self) -> None:
        assert WebViewController._resolve_driver("CDP") == "cdp"
        assert WebViewController._resolve_driver("WebDriver") == "webdriver"
        assert WebViewController._resolve_driver("AUTO") == "webdriver"

    def test_resolve_unsupported_raises(self) -> None:
        with pytest.raises(WebViewOperationError):
            WebViewController._resolve_driver("selenium")


class TestControllerConnect:
    def test_connect_auto_uses_webdriver(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.WebDriverAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:4445", driver="auto")
        assert controller.driver == "webdriver"
        assert controller.url == "http://example.com"

    def test_connect_cdp_uses_cdp(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.CdpAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:9222", driver="cdp")
        assert controller.driver == "cdp"
        assert controller.url == "http://example.com"

    def test_connect_webdriver_explicit(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.WebDriverAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:4445", driver="webdriver")
        assert controller.driver == "webdriver"


class TestControllerApiSurface:
    def test_controller_has_all_expected_methods(self) -> None:
        expected_methods = {
            "click",
            "type_text",
            "get_text",
            "get_attribute",
            "screenshot",
            "execute_script",
            "wait_for_selector",
            "wait_for_load_state",
            "diagnostics_snapshot",
            "disconnect",
        }
        expected_properties = {"driver", "title", "url"}
        controller_methods = {m for m in dir(WebViewController) if not m.startswith("_")}
        controller_properties = expected_properties
        assert expected_methods.issubset(controller_methods), "Missing methods"
        assert controller_properties.issubset(controller_methods), "Missing properties"

    def test_controller_properties(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.WebDriverAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:4445")
        assert controller.driver == "webdriver"
        assert controller.url == "http://example.com"
        assert controller.title == "Test Page"


class TestControllerWaitForLoadState:
    def test_wait_for_load_state_complete(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.WebDriverAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:4445")
        controller.wait_for_load_state("complete")

    def test_wait_for_load_state_unsupported(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.WebDriverAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:4445")
        with pytest.raises(WebViewOperationError):
            controller.wait_for_load_state("invalid_state")


class TestControllerDiagnostics:
    def test_diagnostics_snapshot(self, monkeypatch: pytest.MonkeyPatch) -> None:
        def factory(endpoint: str) -> FakeAdapter:
            return FakeAdapter(endpoint)

        monkeypatch.setattr("nomo_e2e.controller.WebDriverAdapter", factory)
        controller = WebViewController.connect("http://127.0.0.1:4445")
        snapshot = controller.diagnostics_snapshot()
        assert snapshot["driver"] == "webdriver"
        assert snapshot["url"] == "http://example.com"
        assert snapshot["title"] == "Test Page"
        assert snapshot["ready_state"] == "complete"
