"""Integration tests for ChromiumSettingsPatcher.

These tests use real filesystem operations to verify that the
ChromiumSettingsPatcher correctly modifies Local State files.
"""

from __future__ import annotations

import json
from pathlib import Path

import pytest

from electron_angle_patcher.models import PatchResult
from electron_angle_patcher.settings_patcher import ChromiumSettingsPatcher


class TestChromiumSettingsPatcherIntegration:
    """Integration tests for ChromiumSettingsPatcher with real file I/O."""

    def test_patches_empty_local_state(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that patching creates structure from empty file."""
        # Create empty Local State file
        state_file = integration_temp_dir / "Local State"
        state_file.write_text('{"browser": {"enabled_labs_experiments": []}}')

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify file was modified correctly
        data = json.loads(state_file.read_text())
        assert "use-angle@1" in data["browser"]["enabled_labs_experiments"]

    def test_updates_existing_angle_value(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that patching updates use-angle@0 to @1."""
        # Create Local State with wrong angle value
        state_file = integration_temp_dir / "Local State"
        data = {
            "browser": {
                "enabled_labs_experiments": [
                    "use-angle@0",  # Wrong value
                    "other-feature@2",
                ]
            }
        }
        state_file.write_text(json.dumps(data, indent=4))

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify the angle value was updated
        updated = json.loads(state_file.read_text())
        experiments = updated["browser"]["enabled_labs_experiments"]
        assert "use-angle@1" in experiments
        assert "use-angle@0" not in experiments
        assert "other-feature@2" in experiments

    def test_handles_corrupt_file(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that corrupt JSON is replaced with valid structure."""
        # Create corrupt Local State file
        state_file = integration_temp_dir / "Local State"
        state_file.write_text("{invalid json content")

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify file now contains valid JSON with correct structure
        data = json.loads(state_file.read_text())
        assert "browser" in data
        assert "enabled_labs_experiments" in data["browser"]
        assert "use-angle@1" in data["browser"]["enabled_labs_experiments"]

    def test_preserves_other_experiments(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that other experiment flags are preserved."""
        # Create Local State with multiple experiments
        state_file = integration_temp_dir / "Local State"
        data = {
            "browser": {
                "enabled_labs_experiments": [
                    "feature-one@1",
                    "feature-two@2",
                    "feature-three@3",
                ]
            }
        }
        state_file.write_text(json.dumps(data, indent=4))

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify all experiments are preserved
        updated = json.loads(state_file.read_text())
        experiments = updated["browser"]["enabled_labs_experiments"]
        assert "use-angle@1" in experiments
        assert "feature-one@1" in experiments
        assert "feature-two@2" in experiments
        assert "feature-three@3" in experiments
        assert len(experiments) == 4

    def test_already_correct_value_unchanged(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that already correct value is not modified."""
        # Create Local State with correct angle value
        state_file = integration_temp_dir / "Local State"
        data = {
            "browser": {
                "enabled_labs_experiments": [
                    "use-angle@1",  # Already correct
                    "other-feature@2",
                ]
            }
        }
        state_file.write_text(json.dumps(data, indent=4))

        original_content = state_file.read_text()

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify file content is unchanged
        assert state_file.read_text() == original_content

    def test_creates_missing_file(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that missing Local State file is created."""
        # Don't create the file initially
        state_file = integration_temp_dir / "subdir" / "Local State"

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify file was created with correct structure
        assert state_file.exists()
        data = json.loads(state_file.read_text())
        assert "browser" in data
        assert "use-angle@1" in data["browser"]["enabled_labs_experiments"]

    def test_handles_missing_browser_section(
        self,
        integration_temp_dir: Path,
    ) -> None:
        """Test that missing browser section is created."""
        # Create Local State without browser section
        state_file = integration_temp_dir / "Local State"
        data = {"some_other_key": "value"}
        state_file.write_text(json.dumps(data, indent=4))

        # Patch the file
        patcher = ChromiumSettingsPatcher(state_file)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify browser section was added
        updated = json.loads(state_file.read_text())
        assert "browser" in updated
        assert "some_other_key" in updated  # Original key preserved
        assert "use-angle@1" in updated["browser"]["enabled_labs_experiments"]

    def test_tilde_expansion_in_path(
        self,
        integration_temp_dir: Path,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """Test that tilde paths are properly expanded."""
        # Create a state file
        state_file = integration_temp_dir / "Local State"
        state_file.write_text('{"browser": {"enabled_labs_experiments": []}}')

        # Create a path with tilde (simulated)
        tilde_path = Path("~") / state_file.relative_to(integration_temp_dir.parents[-1])

        # Mock home directory
        monkeypatch.setattr("pathlib.Path.expanduser", lambda self: state_file)

        # Patch the file
        patcher = ChromiumSettingsPatcher(tilde_path)
        result = patcher.patch()

        # Verify success
        assert result == PatchResult.SUCCESS

        # Verify the actual file was modified
        assert state_file.exists()
        data = json.loads(state_file.read_text())
        assert "use-angle@1" in data["browser"]["enabled_labs_experiments"]
