"""
Unit tests for the Intel Log Watcher module.

Tests cover:
- Chat message parsing
- Channel name extraction
- Log file path detection
"""

from pathlib import Path
from unittest.mock import patch

from argus_overview.intel.log_watcher import ChatLogWatcher, ChatMessage


class TestChatMessageParsing:
    """Tests for chat message line parsing"""

    def setup_method(self):
        """Setup watcher for each test"""
        self.watcher = ChatLogWatcher()

    def test_parse_standard_line(self):
        """Should parse standard chat log line format"""
        line = "[ 2025.01.29 14:31:45 ] TestPilot > HED-GP hostile Loki"
        msg = self.watcher.parse_line(line, "Alliance")

        assert msg is not None
        assert isinstance(msg, ChatMessage)
        assert msg.speaker == "TestPilot"
        assert msg.message == "HED-GP hostile Loki"
        assert msg.channel == "Alliance"
        assert msg.timestamp.year == 2025
        assert msg.timestamp.month == 1
        assert msg.timestamp.day == 29
        assert msg.timestamp.hour == 14
        assert msg.timestamp.minute == 31
        assert msg.timestamp.second == 45

    def test_parse_line_with_spaces_in_speaker(self):
        """Should parse line with multi-word speaker name"""
        line = "[ 2025.01.29 14:31:45 ] Test Pilot Name > hello world"
        msg = self.watcher.parse_line(line, "Intel")

        assert msg is not None
        assert msg.speaker == "Test Pilot Name"
        assert msg.message == "hello world"

    def test_parse_line_with_special_chars(self):
        """Should parse line with special characters in message"""
        line = "[ 2025.01.29 14:31:45 ] Pilot > HED-GP +5 [gang] <system>"
        msg = self.watcher.parse_line(line, "Intel")

        assert msg is not None
        assert msg.message == "HED-GP +5 [gang] <system>"

    def test_parse_empty_line(self):
        """Should return None for empty line"""
        msg = self.watcher.parse_line("", "Intel")
        assert msg is None

    def test_parse_malformed_line(self):
        """Should return None for malformed line"""
        msg = self.watcher.parse_line("This is not a chat line", "Intel")
        assert msg is None

    def test_parse_line_missing_timestamp(self):
        """Should return None for line without timestamp"""
        msg = self.watcher.parse_line("TestPilot > hello", "Intel")
        assert msg is None

    def test_parse_line_missing_speaker(self):
        """Should return None for line without speaker"""
        msg = self.watcher.parse_line("[ 2025.01.29 14:31:45 ] hello", "Intel")
        assert msg is None


class TestChannelNameExtraction:
    """Tests for channel name extraction from filename"""

    def setup_method(self):
        """Setup watcher for each test"""
        self.watcher = ChatLogWatcher()

    def test_extract_simple_channel_name(self):
        """Should extract simple channel name"""
        path = Path("/logs/Alliance_20250129_143052.txt")
        name = self.watcher._extract_channel_name(path)
        assert name == "Alliance"

    def test_extract_channel_with_spaces(self):
        """Should extract channel name with spaces (underscores)"""
        path = Path("/logs/Standing_Fleet_20250129_143052.txt")
        name = self.watcher._extract_channel_name(path)
        # Returns the part before the date
        assert "Standing" in name or "Fleet" in name

    def test_extract_channel_intel(self):
        """Should extract Intel channel name"""
        path = Path("/logs/Intel_20250129_143052.txt")
        name = self.watcher._extract_channel_name(path)
        assert name == "Intel"


class TestMonitoredChannels:
    """Tests for channel monitoring configuration"""

    def setup_method(self):
        """Setup watcher for each test"""
        self.watcher = ChatLogWatcher()

    def test_set_monitored_channels(self):
        """Should set monitored channels"""
        self.watcher.set_monitored_channels(["Alliance", "Intel"])
        assert "alliance" in self.watcher.monitored_channels
        assert "intel" in self.watcher.monitored_channels

    def test_add_channel(self):
        """Should add channel to monitoring"""
        self.watcher.add_channel("NewChannel")
        assert "newchannel" in self.watcher.monitored_channels

    def test_remove_channel(self):
        """Should remove channel from monitoring"""
        self.watcher.set_monitored_channels(["Alliance", "Intel"])
        self.watcher.remove_channel("Alliance")
        assert "alliance" not in self.watcher.monitored_channels
        assert "intel" in self.watcher.monitored_channels

    def test_channels_case_insensitive(self):
        """Channels should be stored case-insensitively"""
        self.watcher.set_monitored_channels(["ALLIANCE", "Intel"])
        assert "alliance" in self.watcher.monitored_channels
        assert "intel" in self.watcher.monitored_channels


class TestWatcherLifecycle:
    """Tests for watcher start/stop lifecycle"""

    def setup_method(self):
        """Setup watcher for each test"""
        self.watcher = ChatLogWatcher()

    def test_initial_state_not_running(self):
        """Watcher should not be running initially"""
        assert self.watcher.is_running() is False

    def test_start_without_log_dir(self):
        """Should not start if log directory not found"""
        with patch.object(self.watcher, "find_log_directory", return_value=None):
            self.watcher.start()
            # Should emit error but not crash
            assert self.watcher.is_running() is False

    def test_stop_when_not_running(self):
        """Stop should be safe when not running"""
        self.watcher.stop()  # Should not raise
        assert self.watcher.is_running() is False


class TestLogDirectoryDetection:
    """Tests for EVE log directory detection"""

    def setup_method(self):
        """Setup watcher for each test"""
        self.watcher = ChatLogWatcher()

    def test_find_log_directory_none_found(self):
        """Should return None when no log directories exist"""
        with patch("pathlib.Path.exists", return_value=False):
            _result = self.watcher.find_log_directory()
            # May or may not be None depending on actual filesystem
            # Just verify no exception is raised

    def test_custom_log_paths(self):
        """Should accept custom log paths"""
        custom_path = Path("/custom/eve/logs")
        watcher = ChatLogWatcher(log_paths=[custom_path])
        assert custom_path in watcher.custom_log_paths

    def test_set_log_directory_valid(self):
        """Should set valid log directory"""
        with patch("pathlib.Path.exists", return_value=True):
            with patch("pathlib.Path.is_dir", return_value=True):
                path = Path("/valid/logs")
                # Mock the exists and is_dir methods
                with patch.object(Path, "exists", return_value=True):
                    with patch.object(Path, "is_dir", return_value=True):
                        self.watcher.set_log_directory(path)
                        # Verify it was set (may be mocked)
