"""Tests for setup_rules_auto content-aware overwrite logic (UX #17 fix).

Verifies that setup_rules_auto checks file content before deciding
whether to create, update, or skip an IDE adapter file.
"""

from __future__ import annotations

import stat
from typing import TYPE_CHECKING

from beadloom.onboarding.scanner import (
    _BEADLOOM_ADAPTER_MARKERS,
    _RULES_ADAPTER_TEMPLATE,
    _is_beadloom_adapter,
    setup_rules_auto,
)

if TYPE_CHECKING:
    from pathlib import Path


class TestSetupRulesContentAware:
    """Content-aware adapter creation/update/skip logic."""

    def test_creates_adapter_when_file_does_not_exist(self, tmp_path: Path) -> None:
        """Creates adapter file when marker exists but rules file does not."""
        (tmp_path / ".cursor").mkdir()
        result = setup_rules_auto(tmp_path)

        assert ".cursorrules" in result
        assert (tmp_path / ".cursorrules").exists()
        content = (tmp_path / ".cursorrules").read_text()
        assert ".beadloom/AGENTS.md" in content

    def test_updates_adapter_when_file_has_beadloom_marker(self, tmp_path: Path) -> None:
        """Overwrites file when it already contains beadloom adapter content."""
        (tmp_path / ".cursor").mkdir()
        # Write an old-style beadloom adapter.
        old_adapter = "# Beadloom: old adapter\n# See .beadloom/AGENTS.md\n"
        (tmp_path / ".cursorrules").write_text(old_adapter)

        result = setup_rules_auto(tmp_path)

        assert ".cursorrules" in result
        content = (tmp_path / ".cursorrules").read_text()
        # Should be updated to the current template.
        assert content == _RULES_ADAPTER_TEMPLATE

    def test_skips_when_file_has_non_beadloom_content(self, tmp_path: Path) -> None:
        """Does not overwrite file with non-beadloom content."""
        (tmp_path / ".cursor").mkdir()
        user_content = "# My custom Cursor rules\nAlways use TypeScript.\n"
        (tmp_path / ".cursorrules").write_text(user_content)

        result = setup_rules_auto(tmp_path)

        assert ".cursorrules" not in result
        assert (tmp_path / ".cursorrules").read_text() == user_content

    def test_adapter_content_contains_beadloom_marker(self) -> None:
        """The adapter template itself is recognized as a beadloom adapter."""
        # Verify the template contains at least one marker.
        template_lower = _RULES_ADAPTER_TEMPLATE.lower()
        has_marker = any(m in template_lower for m in _BEADLOOM_ADAPTER_MARKERS)
        assert has_marker, "Adapter template must contain a beadloom marker"

    def test_handles_unreadable_files_gracefully(self, tmp_path: Path) -> None:
        """Skips files that cannot be read (e.g., permission denied)."""
        (tmp_path / ".cursor").mkdir()
        rules_file = tmp_path / ".cursorrules"
        rules_file.write_text("some content")
        # Remove read permission.
        rules_file.chmod(0o000)

        try:
            result = setup_rules_auto(tmp_path)
            # Should skip gracefully, not raise.
            assert ".cursorrules" not in result
        finally:
            # Restore permissions for cleanup.
            rules_file.chmod(stat.S_IRUSR | stat.S_IWUSR)


class TestIsBeadloomAdapter:
    """Unit tests for _is_beadloom_adapter helper."""

    def test_returns_true_for_beadloom_content(self, tmp_path: Path) -> None:
        """Returns True when file contains beadloom marker."""
        f = tmp_path / "test.txt"
        f.write_text("# Generated by Beadloom\n")
        assert _is_beadloom_adapter(f) is True

    def test_returns_true_for_agents_md_reference(self, tmp_path: Path) -> None:
        """Returns True when file references .beadloom/AGENTS.md."""
        f = tmp_path / "test.txt"
        f.write_text("Read .beadloom/AGENTS.md before working.\n")
        assert _is_beadloom_adapter(f) is True

    def test_returns_false_for_unrelated_content(self, tmp_path: Path) -> None:
        """Returns False for files without beadloom markers."""
        f = tmp_path / "test.txt"
        f.write_text("# My custom rules\nUse tabs, not spaces.\n")
        assert _is_beadloom_adapter(f) is False

    def test_returns_false_for_empty_file(self, tmp_path: Path) -> None:
        """Returns False for empty files."""
        f = tmp_path / "test.txt"
        f.write_text("")
        assert _is_beadloom_adapter(f) is False

    def test_returns_none_for_unreadable_file(self, tmp_path: Path) -> None:
        """Returns None when file cannot be read."""
        f = tmp_path / "test.txt"
        f.write_text("content")
        f.chmod(0o000)
        try:
            assert _is_beadloom_adapter(f) is None
        finally:
            f.chmod(stat.S_IRUSR | stat.S_IWUSR)

    def test_returns_none_for_nonexistent_file(self, tmp_path: Path) -> None:
        """Returns None when file does not exist."""
        f = tmp_path / "nonexistent.txt"
        assert _is_beadloom_adapter(f) is None

    def test_case_insensitive_match(self, tmp_path: Path) -> None:
        """Marker detection is case-insensitive."""
        f = tmp_path / "test.txt"
        f.write_text("# BEADLOOM adapter\n")
        assert _is_beadloom_adapter(f) is True


class TestSetupRulesWindsurfCline:
    """Tests for windsurf/cline where marker == rules path."""

    def test_windsurf_empty_file_skipped(self, tmp_path: Path) -> None:
        """Empty .windsurfrules (no beadloom marker) is skipped."""
        (tmp_path / ".windsurfrules").write_text("")
        result = setup_rules_auto(tmp_path)
        assert ".windsurfrules" not in result

    def test_windsurf_beadloom_adapter_updated(self, tmp_path: Path) -> None:
        """Windsurf file with beadloom content gets updated."""
        (tmp_path / ".windsurfrules").write_text(
            "# Old beadloom adapter\nRead .beadloom/AGENTS.md\n"
        )
        result = setup_rules_auto(tmp_path)
        assert ".windsurfrules" in result
        content = (tmp_path / ".windsurfrules").read_text()
        assert content == _RULES_ADAPTER_TEMPLATE

    def test_windsurf_user_content_preserved(self, tmp_path: Path) -> None:
        """Windsurf file with user content is not overwritten."""
        user_content = "# My windsurf rules\nPrefer functional style.\n"
        (tmp_path / ".windsurfrules").write_text(user_content)
        result = setup_rules_auto(tmp_path)
        assert ".windsurfrules" not in result
        assert (tmp_path / ".windsurfrules").read_text() == user_content

    def test_cline_beadloom_adapter_updated(self, tmp_path: Path) -> None:
        """Cline file with beadloom content gets updated."""
        (tmp_path / ".clinerules").write_text("# Beadloom pointer\n")
        result = setup_rules_auto(tmp_path)
        assert ".clinerules" in result

    def test_cline_user_content_preserved(self, tmp_path: Path) -> None:
        """Cline file with user content is not overwritten."""
        user_content = "# Custom cline rules\n"
        (tmp_path / ".clinerules").write_text(user_content)
        result = setup_rules_auto(tmp_path)
        assert ".clinerules" not in result
