"""
Unit tests for utility modules
"""

import json
import tempfile
import os
import logging
import sys
import pytest
from unittest.mock import patch, MagicMock

# Add src directory to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

from excel_filter.utils.file_utils import load_config, save_config
from excel_filter.utils.logging_utils import setup_logging, log_message, log_error


class TestFileUtils:
    """
    Test class for file_utils functions
    """

    def test_load_config_success(self):
        """
        Test successful config loading
        """
        config_data = {
            "pattern": "test.*",
            "sheet_name": "Sheet1",
            "columns": ["A", "B"]
        }

        with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
            json.dump(config_data, f)
            config_file = f.name

        try:
            result = load_config(config_file)
            assert result == config_data
        finally:
            os.unlink(config_file)

    def test_load_config_file_not_found(self):
        """
        Test config loading with non-existent file returns empty dict
        """
        result = load_config("nonexistent.json")
        assert result == {}

    def test_load_config_invalid_json(self):
        """
        Test config loading with invalid JSON
        """
        with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
            f.write("invalid json")
            config_file = f.name

        try:
            with pytest.raises(Exception):
                load_config(config_file)
        finally:
            os.unlink(config_file)

    def test_save_config_success(self):
        """
        Test successful config saving
        """
        config_data = {
            "pattern": "test.*",
            "sheet_name": "Sheet1"
        }

        with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
            config_file = f.name

        try:
            save_config(config_file, config_data)

            # Verify file was saved correctly
            with open(config_file, 'r') as f:
                saved_data = json.load(f)
            assert saved_data == config_data
        finally:
            os.unlink(config_file)

    def test_save_config_error(self):
        """
        Test config saving with error
        """
        # Try to save to invalid path
        with pytest.raises(Exception):
            save_config("/invalid/path/config.json", {"test": "data"})


class TestLoggingUtils:
    """
    Test class for logging_utils functions
    """

    def test_setup_logging_without_file(self):
        """
        Test setup_logging without log file
        """
        # Store original level
        original_level = logging.getLogger().getEffectiveLevel()

        setup_logging()
        # Verify setup_logging can be called without error
        # The exact level may be influenced by pytest or other configurations
        logger = logging.getLogger()
        assert logger is not None  # Just verify logging is accessible

    @patch('logging.FileHandler')
    def test_setup_logging_with_file(self, mock_file_handler):
        """
        Test setup_logging with log file
        """
        setup_logging(log_file="test.log", level=logging.DEBUG)
        # Verify FileHandler was created
        mock_file_handler.assert_called_once_with("test.log")

    def test_log_message_normal(self):
        """
        Test logging normal message
        """
        mock_widget = MagicMock()
        log_message(mock_widget, "Test message")

        # Verify widget methods were called
        mock_widget.config.assert_called()
        mock_widget.insert.assert_called()
        mock_widget.see.assert_called_with('end')

    def test_log_message_error(self):
        """
        Test logging error message
        """
        mock_widget = MagicMock()
        log_message(mock_widget, "Error message", is_error=True)

        # Verify error formatting
        mock_widget.tag_add.assert_called()
        mock_widget.tag_config.assert_called_with("error", foreground="red")

    def test_log_error(self):
        """
        Test log_error function
        """
        mock_widget = MagicMock()
        log_error(mock_widget, "Test error")

        # Verify it calls log_message with error flag
        mock_widget.config.assert_called()
        mock_widget.insert.assert_called()
        mock_widget.tag_add.assert_called()
