"""Tests for settings dialog."""

from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

from webdrop_bridge.config import Config, ConfigurationError
from webdrop_bridge.ui.settings_dialog import SettingsDialog


@pytest.fixture
def sample_config(tmp_path):
    """Create sample configuration."""
    return Config(
        app_name="WebDrop Bridge",
        app_version="1.0.0",
        log_level="INFO",
        log_file=None,
        allowed_roots=[Path("/home"), Path("/data")],
        allowed_urls=["http://example.com", "http://*.test.com"],
        webapp_url="http://localhost:8080",
        window_width=800,
        window_height=600,
        window_title="WebDrop Bridge v1.0.0",
        enable_logging=True,
    )


class TestSettingsDialogInitialization:
    """Test settings dialog initialization."""

    def test_dialog_creation(self, qtbot, sample_config):
        """Test dialog can be created."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog is not None
        assert dialog.windowTitle() == "Settings"

    def test_dialog_has_tabs(self, qtbot, sample_config):
        """Test dialog has all required tabs."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs is not None
        assert dialog.tabs.count() == 5  # Paths, URLs, Logging, Window, Profiles

    def test_dialog_has_paths_tab(self, qtbot, sample_config):
        """Test Paths tab exists."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs.tabText(0) == "Paths"

    def test_dialog_has_urls_tab(self, qtbot, sample_config):
        """Test URLs tab exists."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs.tabText(1) == "URLs"

    def test_dialog_has_logging_tab(self, qtbot, sample_config):
        """Test Logging tab exists."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs.tabText(2) == "Logging"

    def test_dialog_has_window_tab(self, qtbot, sample_config):
        """Test Window tab exists."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs.tabText(3) == "Window"

    def test_dialog_has_profiles_tab(self, qtbot, sample_config):
        """Test Profiles tab exists."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs.tabText(4) == "Profiles"


class TestPathsTab:
    """Test Paths configuration tab."""

    def test_paths_loaded_from_config(self, qtbot, sample_config):
        """Test paths are loaded from configuration."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        items = [dialog.paths_list.item(i).text() for i in range(dialog.paths_list.count())]
        assert len(items) == 2
        # Paths are normalized (backslashes on Windows)
        assert any("home" in item for item in items)
        assert any("data" in item for item in items)

    def test_add_path_button_exists(self, qtbot, sample_config):
        """Test Add Path button exists."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.tabs.currentWidget() is not None


class TestURLsTab:
    """Test URLs configuration tab."""

    def test_urls_loaded_from_config(self, qtbot, sample_config):
        """Test URLs are loaded from configuration."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        items = [dialog.urls_list.item(i).text() for i in range(dialog.urls_list.count())]
        assert len(items) == 2
        assert "http://example.com" in items
        assert "http://*.test.com" in items


class TestLoggingTab:
    """Test Logging configuration tab."""

    def test_log_level_set_from_config(self, qtbot, sample_config):
        """Test log level is set from configuration."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.log_level_combo.currentText() == "INFO"

    def test_log_levels_available(self, qtbot, sample_config):
        """Test all log levels are available."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        levels = [dialog.log_level_combo.itemText(i) for i in range(dialog.log_level_combo.count())]
        assert "DEBUG" in levels
        assert "INFO" in levels
        assert "WARNING" in levels
        assert "ERROR" in levels
        assert "CRITICAL" in levels


class TestWindowTab:
    """Test Window configuration tab."""

    def test_window_width_set_from_config(self, qtbot, sample_config):
        """Test window width is set from configuration."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.width_spin.value() == 800

    def test_window_height_set_from_config(self, qtbot, sample_config):
        """Test window height is set from configuration."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.height_spin.value() == 600

    def test_window_width_has_min_max(self, qtbot, sample_config):
        """Test window width spinbox has min/max."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.width_spin.minimum() == 400
        assert dialog.width_spin.maximum() == 5000

    def test_window_height_has_min_max(self, qtbot, sample_config):
        """Test window height spinbox has min/max."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.height_spin.minimum() == 300
        assert dialog.height_spin.maximum() == 5000


class TestProfilesTab:
    """Test Profiles management tab."""

    def test_profiles_list_initialized(self, qtbot, sample_config):
        """Test profiles list is initialized."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        assert dialog.profiles_list is not None


class TestConfigDataRetrieval:
    """Test getting configuration data from dialog."""

    def test_get_config_data_from_dialog(self, qtbot, sample_config):
        """Test retrieving configuration data from dialog."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        config_data = dialog.get_config_data()
        
        assert config_data["app_name"] == "WebDrop Bridge"
        assert config_data["log_level"] == "INFO"
        assert config_data["window_width"] == 800
        assert config_data["window_height"] == 600

    def test_get_config_data_validates(self, qtbot, sample_config):
        """Test get_config_data returns valid configuration data."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        # All default values are valid
        config_data = dialog.get_config_data()
        assert config_data is not None
        assert config_data["window_width"] == 800

    def test_get_config_data_with_modified_values(self, qtbot, sample_config):
        """Test get_config_data returns modified values."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        # Modify values
        dialog.width_spin.setValue(1024)
        dialog.height_spin.setValue(768)
        dialog.log_level_combo.setCurrentText("DEBUG")
        
        config_data = dialog.get_config_data()
        
        assert config_data["window_width"] == 1024
        assert config_data["window_height"] == 768
        assert config_data["log_level"] == "DEBUG"


class TestApplyConfigData:
    """Test applying configuration data to dialog."""

    def test_apply_config_data_updates_paths(self, qtbot, sample_config):
        """Test applying config data updates paths."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        new_config = {
            "app_name": "Test",
            "app_version": "1.0.0",
            "log_level": "INFO",
            "log_file": None,
            "allowed_roots": ["/new/path", "/another/path"],
            "allowed_urls": [],
            "webapp_url": "http://localhost",
            "window_width": 800,
            "window_height": 600,
            "enable_logging": True,
        }
        
        dialog._apply_config_data(new_config)
        
        items = [dialog.paths_list.item(i).text() for i in range(dialog.paths_list.count())]
        assert "/new/path" in items
        assert "/another/path" in items

    def test_apply_config_data_updates_urls(self, qtbot, sample_config):
        """Test applying config data updates URLs."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        new_config = {
            "app_name": "Test",
            "app_version": "1.0.0",
            "log_level": "INFO",
            "log_file": None,
            "allowed_roots": [],
            "allowed_urls": ["http://new.com", "http://test.org"],
            "webapp_url": "http://localhost",
            "window_width": 800,
            "window_height": 600,
            "enable_logging": True,
        }
        
        dialog._apply_config_data(new_config)
        
        items = [dialog.urls_list.item(i).text() for i in range(dialog.urls_list.count())]
        assert "http://new.com" in items
        assert "http://test.org" in items

    def test_apply_config_data_updates_window_size(self, qtbot, sample_config):
        """Test applying config data updates window size."""
        dialog = SettingsDialog(sample_config)
        qtbot.addWidget(dialog)
        
        new_config = {
            "app_name": "Test",
            "app_version": "1.0.0",
            "log_level": "INFO",
            "log_file": None,
            "allowed_roots": [],
            "allowed_urls": [],
            "webapp_url": "http://localhost",
            "window_width": 1280,
            "window_height": 1024,
            "enable_logging": True,
        }
        
        dialog._apply_config_data(new_config)
        
        assert dialog.width_spin.value() == 1280
        assert dialog.height_spin.value() == 1024
