"""Unit tests for selector utilities."""

import pytest
from playwright_healer.utils import (
    SelectorType,
    detect_selector_type,
    css_id_from_selector,
    css_classes_from_selector,
    strip_dom_for_ai,
    ElementFingerprint,
    make_css_from_fingerprint,
)


class TestSelectorTypeDetection:
    def test_css_id(self):
        assert detect_selector_type("#submit-btn") == SelectorType.CSS

    def test_css_class(self):
        assert detect_selector_type(".btn-primary") == SelectorType.CSS

    def test_css_attribute(self):
        assert detect_selector_type("[data-testid='login']") == SelectorType.CSS

    def test_xpath_absolute(self):
        assert detect_selector_type("//button[@id='submit']") == SelectorType.XPATH

    def test_xpath_relative(self):
        assert detect_selector_type(".//input[@name='username']") == SelectorType.XPATH

    def test_role_button(self):
        assert detect_selector_type("button::Submit") == SelectorType.ROLE

    def test_role_textbox(self):
        assert detect_selector_type("textbox::Username") == SelectorType.ROLE

    def test_css_complex(self):
        assert detect_selector_type("form > input.email") == SelectorType.CSS


class TestCssHelpers:
    def test_extract_id(self):
        assert css_id_from_selector("#my-btn") == "my-btn"

    def test_extract_id_with_dashes(self):
        assert css_id_from_selector("#submit-login-btn") == "submit-login-btn"

    def test_extract_id_none_for_non_id(self):
        assert css_id_from_selector(".btn") is None

    def test_extract_classes(self):
        classes = css_classes_from_selector(".btn.primary.large")
        assert "btn" in classes
        assert "primary" in classes
        assert "large" in classes

    def test_extract_classes_empty(self):
        assert css_classes_from_selector("#some-id") == []


class TestDomStripping:
    def test_removes_scripts(self):
        html = "<html><head><script>alert(1)</script></head><body><button>OK</button></body></html>"
        result = strip_dom_for_ai(html)
        assert "alert(1)" not in result
        assert "OK" in result or "button" in result.lower()

    def test_truncates_large_html(self):
        large = "<html><body>" + "<div>x</div>" * 2000 + "</body></html>"
        result = strip_dom_for_ai(large, max_chars=8000)
        assert len(result) <= 8000

    def test_handles_invalid_html(self):
        result = strip_dom_for_ai("not html", max_chars=8000)
        assert isinstance(result, str)


class TestFingerprintCssGen:
    def test_generates_id_selector(self):
        fp = ElementFingerprint(id="submit-btn")
        candidates = make_css_from_fingerprint(fp)
        assert "#submit-btn" in candidates

    def test_generates_testid_selector(self):
        fp = ElementFingerprint(data_testid="login-form")
        candidates = make_css_from_fingerprint(fp)
        assert '[data-testid="login-form"]' in candidates

    def test_generates_name_selector(self):
        fp = ElementFingerprint(name="username")
        candidates = make_css_from_fingerprint(fp)
        assert '[name="username"]' in candidates

    def test_multiple_candidates(self):
        fp = ElementFingerprint(id="x", data_testid="y", name="z")
        candidates = make_css_from_fingerprint(fp)
        assert len(candidates) >= 3
