"""Tests for shell config step."""

from __future__ import annotations

import tempfile
from pathlib import Path
from unittest.mock import patch

from installer.steps.shell_config import (
    ALIAS_MARKER,
    SF_BIN,
    ShellConfigStep,
    alias_exists_in_file,
    get_alias_lines,
    remove_old_alias,
)


class TestShellConfigStep:
    """Test ShellConfigStep class."""

    def test_shell_config_step_has_correct_name(self):
        """ShellConfigStep has name 'shell_config'."""
        step = ShellConfigStep()
        assert step.name == "shell_config"

    def test_shell_config_check_always_returns_false(self):
        """ShellConfigStep.check always returns False to ensure alias updates."""
        from installer.context import InstallContext
        from installer.ui import Console

        step = ShellConfigStep()
        with tempfile.TemporaryDirectory() as tmpdir:
            ctx = InstallContext(
                project_dir=Path(tmpdir),
                ui=Console(non_interactive=True),
            )
            assert step.check(ctx) is False

    @patch("installer.steps.shell_config.get_shell_config_files")
    def test_shell_config_run_adds_aliases(self, mock_get_files):
        """ShellConfigStep.run adds tribunal and sfc aliases to shell configs."""
        from installer.context import InstallContext
        from installer.ui import Console

        step = ShellConfigStep()
        with tempfile.TemporaryDirectory() as tmpdir:
            bashrc = Path(tmpdir) / ".bashrc"
            bashrc.write_text("# existing config\n")
            mock_get_files.return_value = [bashrc]

            ctx = InstallContext(
                project_dir=Path(tmpdir),
                ui=Console(non_interactive=True),
            )

            step.run(ctx)

            content = bashrc.read_text()
            assert ALIAS_MARKER in content
            assert "alias tribunal=" in content
            assert "alias sfc=" in content
            assert SF_BIN in content


class TestAliasLines:
    """Test alias line generation."""

    def test_get_alias_lines_returns_string(self):
        """get_alias_lines returns a string."""
        result = get_alias_lines("bash")
        assert isinstance(result, str)
        assert len(result) > 0

    def test_get_alias_lines_contains_tribunal_and_sfc_aliases(self):
        """Alias lines contain tribunal and sfc aliases."""
        result = get_alias_lines("bash")
        assert "alias tribunal=" in result
        assert "alias sfc=" in result
        assert SF_BIN in result
        assert ALIAS_MARKER in result

    def test_get_alias_lines_fish_uses_alias_syntax(self):
        """Fish alias uses alias syntax for tribunal and sfc aliases."""
        result = get_alias_lines("fish")
        assert "alias tribunal=" in result
        assert "alias sfc=" in result
        assert SF_BIN in result
        assert ALIAS_MARKER in result


class TestAliasDetection:
    """Test alias detection in config files."""

    def test_alias_exists_in_file_detects_marker(self):
        """alias_exists_in_file detects alias marker."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text(f"{ALIAS_MARKER}\nalias tribunal='...'\n")
            assert alias_exists_in_file(config) is True

    def test_alias_exists_in_file_detects_tribunal_alias(self):
        """alias_exists_in_file detects alias tribunal without marker."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text("alias tribunal='something'\n")
            assert alias_exists_in_file(config) is True

    def test_alias_exists_in_file_detects_sfc_alias(self):
        """alias_exists_in_file detects alias sfc without marker."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text("alias sfc='something'\n")
            assert alias_exists_in_file(config) is True

    def test_alias_exists_in_file_returns_false_when_missing(self):
        """alias_exists_in_file returns False when not configured."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text("# some other config\n")
            assert alias_exists_in_file(config) is False


class TestAliasRemoval:
    """Test alias removal for updates."""

    def test_remove_old_alias_removes_marker_and_alias(self):
        """remove_old_alias removes marker and alias lines."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text(f"# before\n{ALIAS_MARKER}\nalias tribunal='...'\nalias sfc='...'\n# after\n")

            result = remove_old_alias(config)

            assert result is True
            content = config.read_text()
            assert "alias tribunal" not in content
            assert "alias sfc" not in content
            assert ALIAS_MARKER not in content
            assert "# before" in content
            assert "# after" in content

    def test_remove_old_alias_removes_tribunal_function(self):
        """remove_old_alias removes tribunal() function definition."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text(f'# before\n{ALIAS_MARKER}\ntribunal() {{\n    echo "hello"\n}}\n# after\n')

            result = remove_old_alias(config)

            assert result is True
            content = config.read_text()
            assert ALIAS_MARKER not in content
            assert "tribunal()" not in content
            assert "# before" in content
            assert "# after" in content

    def test_remove_old_alias_removes_fish_function(self):
        """remove_old_alias removes fish function definition."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / "config.fish"
            config.write_text("# before\nfunction tribunal\n    echo 'hello'\nend\n# after\n")

            result = remove_old_alias(config)

            assert result is True
            content = config.read_text()
            assert "function tribunal" not in content
            assert "# before" in content
            assert "# after" in content

    def test_remove_old_alias_returns_false_when_no_alias(self):
        """remove_old_alias returns False when no alias exists."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config = Path(tmpdir) / ".bashrc"
            config.write_text("# just config\n")

            result = remove_old_alias(config)

            assert result is False
