"""Settings dialog for configuration management."""

import logging
from pathlib import Path
from typing import Any, Dict, Optional

from PySide6.QtGui import QIcon, QPixmap
from PySide6.QtWidgets import (
    QComboBox,
    QDialog,
    QDialogButtonBox,
    QFileDialog,
    QHBoxLayout,
    QInputDialog,
    QLabel,
    QLineEdit,
    QListWidget,
    QPushButton,
    QSpinBox,
    QTableWidget,
    QTableWidgetItem,
    QTabWidget,
    QVBoxLayout,
    QWidget,
)

from webdrop_bridge.config import Config, ConfigurationError
from webdrop_bridge.core.branding_manager import BrandingManager
from webdrop_bridge.core.config_manager import ConfigExporter, ConfigProfile, ConfigValidator
from webdrop_bridge.utils.i18n import get_available_languages, tr
from webdrop_bridge.utils.logging import reconfigure_logging

logger = logging.getLogger(__name__)


class SettingsDialog(QDialog):
    """Dialog for managing application settings and configuration."""

    def __init__(self, config: Config, parent: Optional[QWidget] = None):
        """Initialize the settings dialog.

        Args:
            config: Current application configuration
            parent: Parent widget
        """
        super().__init__(parent)
        self.config = config
        self.branding_manager = BrandingManager()
        self.profile_manager = ConfigProfile(config.config_dir_name)
        self.setWindowTitle(tr("settings.title"))
        self.setGeometry(100, 100, 600, 500)

        self.setup_ui()

    def setup_ui(self) -> None:
        """Set up the dialog UI with tabs."""
        layout = QVBoxLayout()

        self.tabs = QTabWidget()
        self.tabs.addTab(self._create_general_tab(), tr("settings.tab.general"))
        self.tabs.addTab(self._create_branding_tab(), tr("settings.tab.branding"))
        self.tabs.addTab(self._create_web_source_tab(), tr("settings.tab.web_source"))
        self.tabs.addTab(self._create_paths_tab(), tr("settings.tab.paths"))
        self.tabs.addTab(self._create_urls_tab(), tr("settings.tab.urls"))
        self.tabs.addTab(self._create_logging_tab(), tr("settings.tab.logging"))
        self.tabs.addTab(self._create_window_tab(), tr("settings.tab.window"))
        self.tabs.addTab(self._create_profiles_tab(), tr("settings.tab.profiles"))
        layout.addWidget(self.tabs)

        button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
        )
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)

        self.setLayout(layout)

    def accept(self) -> None:
        """Handle OK button - save configuration changes to file."""
        try:
            config_data = self.get_config_data()

            from webdrop_bridge.config import URLMapping

            url_mappings = [
                URLMapping(url_prefix=m["url_prefix"], local_path=m["local_path"])
                for m in config_data["url_mappings"]
            ]

            selected_branding_id = config_data.get(
                "active_branding_id", self.config.active_branding_id
            )
            old_branding_id = self.config.active_branding_id
            self.branding_manager.set_active_branding_id(selected_branding_id)
            self.config.active_branding_id = selected_branding_id
            self.branding_manager.apply_to_config(self.config)

            old_log_level = self.config.log_level
            self.config.language = config_data["language"]
            self.config.log_level = config_data["log_level"]
            self.config.log_file = (
                Path(config_data["log_file"]) if config_data["log_file"] else None
            )
            self.config.allowed_roots = [Path(r).resolve() for r in config_data["allowed_roots"]]
            self.config.allowed_urls = config_data["allowed_urls"]
            self.config.webapp_url = config_data["webapp_url"]
            self.config.url_mappings = url_mappings
            self.config.window_width = config_data["window_width"]
            self.config.window_height = config_data["window_height"]

            config_path = self.config.get_config_path()
            self.config.to_file(config_path)

            logger.info(f"Configuration saved to {config_path}")
            logger.info(f"  Log level: {self.config.log_level} (was: {old_log_level})")
            logger.info(f"  Window size: {self.config.window_width}x{self.config.window_height}")
            if old_branding_id != self.config.active_branding_id:
                logger.info(
                    "  Active branding changed: %s -> %s",
                    old_branding_id,
                    self.config.active_branding_id,
                )

            if old_log_level != self.config.log_level:
                reconfigure_logging(
                    logger_name="webdrop_bridge",
                    level=self.config.log_level,
                    log_file=self.config.log_file,
                )
                logger.info(f"Log level updated to {self.config.log_level}")

            super().accept()

        except ConfigurationError as e:
            logger.error(f"Configuration error: {e}")
            self._show_error(f"Configuration Error:\n\n{e}")
        except Exception as e:
            logger.error(f"Failed to save configuration: {e}", exc_info=True)
            self._show_error(f"Failed to save configuration:\n\n{e}")

    def _create_general_tab(self) -> QWidget:
        """Create general settings tab with language selector."""
        widget = QWidget()
        layout = QVBoxLayout()

        lang_layout = QHBoxLayout()
        lang_layout.addWidget(QLabel(tr("settings.general.language_label")))

        self.language_combo = QComboBox()
        self.language_combo.addItem(tr("settings.general.language_auto"), "auto")
        available = get_available_languages()
        current_lang = self.config.language
        for code, name in available.items():
            self.language_combo.addItem(name, code)

        idx = self.language_combo.findData(current_lang)
        if idx >= 0:
            self.language_combo.setCurrentIndex(idx)

        lang_layout.addWidget(self.language_combo)
        lang_layout.addStretch()
        layout.addLayout(lang_layout)

        note = QLabel(tr("settings.general.language_restart_note"))
        note.setStyleSheet("color: gray; font-size: 11px;")
        layout.addWidget(note)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def _create_branding_tab(self) -> QWidget:
        """Create runtime branding tab."""
        widget = QWidget()
        layout = QVBoxLayout()

        label = QLabel(tr("settings.branding.select_label"))
        label.setToolTip(tr("settings.branding.select_tooltip"))
        layout.addWidget(label)

        help_label = QLabel(tr("settings.branding.help_text"))
        help_label.setWordWrap(True)
        help_label.setStyleSheet("color: gray; font-size: 11px;")
        layout.addWidget(help_label)

        self.branding_combo = QComboBox()
        self.branding_combo.setToolTip(tr("settings.branding.select_tooltip"))
        self._refresh_branding_combo()
        self.branding_combo.currentIndexChanged.connect(self._on_branding_selection_changed)
        layout.addWidget(self.branding_combo)

        self.branding_display_name_input = QLineEdit()
        self.branding_display_name_input.setPlaceholderText(
            tr("settings.branding.display_name_label")
        )
        self.branding_display_name_input.textChanged.connect(self._update_branding_preview)
        layout.addWidget(QLabel(tr("settings.branding.display_name_label")))
        layout.addWidget(self.branding_display_name_input)

        self.branding_app_name_input = QLineEdit()
        self.branding_app_name_input.setPlaceholderText(tr("settings.branding.app_name_label"))
        self.branding_app_name_input.textChanged.connect(self._update_branding_preview)
        layout.addWidget(QLabel(tr("settings.branding.app_name_label")))
        layout.addWidget(self.branding_app_name_input)

        self.branding_window_title_input = QLineEdit()
        self.branding_window_title_input.setPlaceholderText(
            tr("settings.branding.window_title_label")
        )
        self.branding_window_title_input.textChanged.connect(self._update_branding_preview)
        layout.addWidget(QLabel(tr("settings.branding.window_title_label")))
        layout.addWidget(self.branding_window_title_input)

        layout.addWidget(QLabel(tr("settings.branding.logo_path_label")))
        logo_layout = QHBoxLayout()
        self.branding_logo_path_input = QLineEdit()
        self.branding_logo_path_input.setPlaceholderText(tr("settings.branding.logo_path_label"))
        self.branding_logo_path_input.textChanged.connect(self._update_branding_preview)
        logo_layout.addWidget(self.branding_logo_path_input)

        self.browse_branding_logo_btn = QPushButton(tr("settings.log_file.browse_btn"))
        self.browse_branding_logo_btn.clicked.connect(self._browse_branding_logo)
        logo_layout.addWidget(self.browse_branding_logo_btn)
        layout.addLayout(logo_layout)

        layout.addWidget(QLabel(tr("settings.branding.preview_label")))
        self.branding_preview_name_label = QLabel()
        self.branding_preview_name_label.setStyleSheet("font-weight: bold;")
        layout.addWidget(self.branding_preview_name_label)

        self.branding_preview_title_label = QLabel()
        self.branding_preview_title_label.setStyleSheet("color: gray;")
        layout.addWidget(self.branding_preview_title_label)

        self.branding_preview_icon_label = QLabel(tr("settings.branding.no_icon_selected"))
        self.branding_preview_icon_label.setFixedSize(72, 72)
        self.branding_preview_icon_label.setStyleSheet(
            "border: 1px solid #ccc; padding: 4px; background: #fafafa;"
        )
        layout.addWidget(self.branding_preview_icon_label)

        branding_button_layout = QHBoxLayout()
        self.save_branding_as_btn = QPushButton(tr("settings.branding.save_as_btn"))
        self.save_branding_as_btn.clicked.connect(self._save_branding_as)
        branding_button_layout.addWidget(self.save_branding_as_btn)

        self.export_branding_btn = QPushButton(tr("settings.branding.export_btn"))
        self.export_branding_btn.clicked.connect(self._export_branding)
        branding_button_layout.addWidget(self.export_branding_btn)

        self.import_branding_btn = QPushButton(tr("settings.branding.import_btn"))
        self.import_branding_btn.clicked.connect(self._import_branding)
        branding_button_layout.addWidget(self.import_branding_btn)

        self.delete_branding_btn = QPushButton(tr("settings.branding.delete_btn"))
        self.delete_branding_btn.clicked.connect(self._delete_branding)
        branding_button_layout.addWidget(self.delete_branding_btn)
        layout.addLayout(branding_button_layout)

        self._load_branding_into_editor(self.branding_combo.currentData() or "default")

        note = QLabel(tr("settings.branding.restart_note"))
        note.setWordWrap(True)
        note.setStyleSheet("color: gray; font-size: 11px;")
        layout.addWidget(note)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def _refresh_branding_combo(self, selected_template_id: Optional[str] = None) -> None:
        """Refresh the branding template selector."""
        current = selected_template_id or self.config.active_branding_id or "default"
        self.branding_combo.blockSignals(True)
        self.branding_combo.clear()
        for template in self.branding_manager.list_templates():
            self.branding_combo.addItem(template.display_name, template.template_id)

        idx = self.branding_combo.findData(current)
        if idx < 0:
            idx = self.branding_combo.findData("default")
        if idx >= 0:
            self.branding_combo.setCurrentIndex(idx)
        self.branding_combo.blockSignals(False)

    def _load_branding_into_editor(self, template_id: str) -> None:
        """Load the selected branding into the editable fields."""
        template = self.branding_manager.load_template(template_id)
        self.branding_display_name_input.setText(template.display_name)
        self.branding_app_name_input.setText(template.app_name)
        self.branding_window_title_input.setText(
            template.window_title or f"{template.app_name} v{self.config.app_version}"
        )
        self.branding_logo_path_input.setText(template.logo_path or template.get_app_icon_path())
        self._update_branding_preview()

    def _resolve_branding_preview_path(self, configured_path: str) -> Optional[Path]:
        """Resolve a branding preview path in both dev and packaged layouts."""
        if not configured_path:
            return None

        path = Path(configured_path)
        candidates = [path] if path.is_absolute() else [Path.cwd() / path]
        if not path.is_absolute():
            project_root = Path(__file__).resolve().parents[3]
            candidates.append(project_root / path)

        for candidate in candidates:
            if candidate.exists() and candidate.is_file():
                return candidate

        return None

    def _update_branding_preview(self) -> None:
        """Refresh the small branding preview for name and icon."""
        display_name = self.branding_display_name_input.text().strip() or tr(
            "settings.branding.preview_default_name"
        )
        self.branding_preview_name_label.setText(display_name)

        effective_title = self.branding_window_title_input.text().strip() or (
            self.branding_app_name_input.text().strip() or display_name
        )
        self.branding_preview_title_label.setText(effective_title)

        logo_path = self.branding_logo_path_input.text().strip()
        resolved_logo_path = self._resolve_branding_preview_path(logo_path)
        if resolved_logo_path:
            pixmap = QPixmap(str(resolved_logo_path))
            if pixmap.isNull():
                icon = QIcon(str(resolved_logo_path))
                pixmap = icon.pixmap(64, 64)

            if not pixmap.isNull():
                self.branding_preview_icon_label.setPixmap(pixmap.scaled(64, 64))
                self.branding_preview_icon_label.setText("")
                return

        self.branding_preview_icon_label.setPixmap(QPixmap())
        self.branding_preview_icon_label.setText(tr("settings.branding.no_icon_selected"))

    def _on_branding_selection_changed(self) -> None:
        """Update editable branding fields when a different template is selected."""
        template_id = self.branding_combo.currentData()
        if template_id:
            self._load_branding_into_editor(template_id)

    def _browse_branding_logo(self) -> None:
        """Select an external logo or icon file for the current branding."""
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            tr("settings.branding.logo_path_label"),
            str(Path.home()),
            "Image Files (*.png *.jpg *.jpeg *.svg *.ico *.icns *.bmp);;All Files (*)",
        )
        if file_path:
            self.branding_logo_path_input.setText(file_path)

    def _save_branding_as(self) -> None:
        """Save the edited branding as a new reusable branding entry."""
        branding_name, ok = QInputDialog.getText(
            self,
            tr("settings.branding.save_as_title"),
            tr("settings.branding.save_as_prompt"),
            text=self.branding_display_name_input.text().strip(),
        )

        if not ok or not branding_name:
            return

        try:
            display_name = self.branding_display_name_input.text().strip() or branding_name
            app_name = self.branding_app_name_input.text().strip() or display_name
            window_title = self.branding_window_title_input.text().strip()
            template = self.branding_manager.build_template(
                template_id=branding_name,
                display_name=display_name,
                app_name=app_name,
                window_title=window_title,
                logo_path=self.branding_logo_path_input.text(),
            )
            self.branding_manager.save_template(template)
            self._refresh_branding_combo(template.template_id)
            self._load_branding_into_editor(template.template_id)
        except ConfigurationError as e:
            self._show_error(f"Failed to save branding: {e}")

    def _export_branding(self) -> None:
        """Export the selected branding so it can be shared with other users."""
        template_id = self.branding_combo.currentData()
        if not template_id:
            return

        file_path, _ = QFileDialog.getSaveFileName(
            self,
            tr("settings.branding.export_title"),
            str(Path.home() / f"{template_id}.json"),
            "JSON Files (*.json);;All Files (*)",
        )
        if not file_path:
            return

        try:
            self.branding_manager.export_template(template_id, Path(file_path))
        except ConfigurationError as e:
            self._show_error(f"Failed to export branding: {e}")

    def _import_branding(self) -> None:
        """Import a branding package from another user."""
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            tr("settings.branding.import_title"),
            str(Path.home()),
            "JSON Files (*.json);;All Files (*)",
        )
        if not file_path:
            return

        try:
            template = self.branding_manager.import_template(Path(file_path))
            self._refresh_branding_combo(template.template_id)
            self._load_branding_into_editor(template.template_id)
        except ConfigurationError as e:
            self._show_error(f"Failed to import branding: {e}")

    def _delete_branding(self) -> None:
        """Delete the currently selected custom branding."""
        template_id = self.branding_combo.currentData()
        if not template_id:
            return

        try:
            self.branding_manager.delete_template(template_id)
            self._refresh_branding_combo("default")
            self._load_branding_into_editor("default")
        except ConfigurationError as e:
            self._show_error(f"Failed to delete branding: {e}")

    def _create_web_source_tab(self) -> QWidget:
        """Create web source configuration tab."""
        widget = QWidget()
        layout = QVBoxLayout()

        layout.addWidget(QLabel(tr("settings.web_source.url_label")))
        url_layout = QHBoxLayout()

        self.webapp_url_input = QLineEdit()
        self.webapp_url_input.setText(self.config.webapp_url)
        self.webapp_url_input.setPlaceholderText(
            "e.g., http://localhost:8080 or file:///./webapp/index.html"
        )
        url_layout.addWidget(self.webapp_url_input)

        open_btn = QPushButton(tr("settings.web_source.open_btn"))
        open_btn.clicked.connect(self._open_webapp_url)
        url_layout.addWidget(open_btn)

        layout.addLayout(url_layout)

        layout.addWidget(QLabel(tr("settings.web_source.url_mappings_label")))

        self.url_mappings_table = QTableWidget()
        self.url_mappings_table.setColumnCount(2)
        self.url_mappings_table.setHorizontalHeaderLabels(
            [
                tr("settings.web_source.col_url_prefix"),
                tr("settings.web_source.col_local_path"),
            ]
        )
        self.url_mappings_table.horizontalHeader().setStretchLastSection(True)

        for mapping in self.config.url_mappings:
            row = self.url_mappings_table.rowCount()
            self.url_mappings_table.insertRow(row)
            self.url_mappings_table.setItem(row, 0, QTableWidgetItem(mapping.url_prefix))
            self.url_mappings_table.setItem(row, 1, QTableWidgetItem(mapping.local_path))

        layout.addWidget(self.url_mappings_table)

        button_layout = QHBoxLayout()

        add_mapping_btn = QPushButton(tr("settings.web_source.add_mapping_btn"))
        add_mapping_btn.clicked.connect(self._add_url_mapping)
        button_layout.addWidget(add_mapping_btn)

        edit_mapping_btn = QPushButton(tr("settings.web_source.edit_mapping_btn"))
        edit_mapping_btn.clicked.connect(self._edit_url_mapping)
        button_layout.addWidget(edit_mapping_btn)

        remove_mapping_btn = QPushButton(tr("settings.web_source.remove_mapping_btn"))
        remove_mapping_btn.clicked.connect(self._remove_url_mapping)
        button_layout.addWidget(remove_mapping_btn)

        layout.addLayout(button_layout)
        layout.addStretch()

        widget.setLayout(layout)
        return widget

    def _open_webapp_url(self) -> None:
        """Open the webapp URL in the default browser."""
        import webbrowser

        url = self.webapp_url_input.text().strip()
        if not url:
            return
        try:
            webbrowser.open(url)
        except Exception as e:
            logger.error(f"Failed to open URL: {e}")
            self._show_error(f"Failed to open URL:\n\n{e}")

    def _add_url_mapping(self) -> None:
        """Add new URL mapping."""
        from PySide6.QtWidgets import QInputDialog

        url_prefix, ok1 = QInputDialog.getText(
            self,
            tr("settings.web_source.add_mapping_title"),
            tr("settings.web_source.add_mapping_url_prompt"),
        )

        if ok1 and url_prefix:
            local_path, ok2 = QInputDialog.getText(
                self,
                tr("settings.web_source.add_mapping_title"),
                tr("settings.web_source.add_mapping_path_prompt"),
            )

            if ok2 and local_path:
                row = self.url_mappings_table.rowCount()
                self.url_mappings_table.insertRow(row)
                self.url_mappings_table.setItem(row, 0, QTableWidgetItem(url_prefix))
                self.url_mappings_table.setItem(row, 1, QTableWidgetItem(local_path))

    def _edit_url_mapping(self) -> None:
        """Edit selected URL mapping."""
        from PySide6.QtWidgets import QInputDialog

        current_row = self.url_mappings_table.currentRow()
        if current_row < 0:
            self._show_error(tr("settings.web_source.select_mapping_to_edit"))
            return

        url_prefix = self.url_mappings_table.item(current_row, 0).text()  # type: ignore
        local_path = self.url_mappings_table.item(current_row, 1).text()  # type: ignore

        new_url_prefix, ok1 = QInputDialog.getText(
            self,
            tr("settings.web_source.edit_mapping_title"),
            tr("settings.web_source.edit_mapping_url_prompt"),
            text=url_prefix,
        )

        if ok1 and new_url_prefix:
            new_local_path, ok2 = QInputDialog.getText(
                self,
                tr("settings.web_source.edit_mapping_title"),
                tr("settings.web_source.edit_mapping_path_prompt"),
                text=local_path,
            )

            if ok2 and new_local_path:
                self.url_mappings_table.setItem(current_row, 0, QTableWidgetItem(new_url_prefix))
                self.url_mappings_table.setItem(current_row, 1, QTableWidgetItem(new_local_path))

    def _remove_url_mapping(self) -> None:
        """Remove selected URL mapping."""
        current_row = self.url_mappings_table.currentRow()
        if current_row >= 0:
            self.url_mappings_table.removeRow(current_row)

    def _create_paths_tab(self) -> QWidget:
        """Create paths configuration tab."""
        widget = QWidget()
        layout = QVBoxLayout()

        layout.addWidget(QLabel(tr("settings.paths.label")))

        self.paths_list = QListWidget()
        for path in self.config.allowed_roots:
            self.paths_list.addItem(str(path))
        layout.addWidget(self.paths_list)

        button_layout = QHBoxLayout()

        add_path_btn = QPushButton(tr("settings.paths.add_btn"))
        add_path_btn.clicked.connect(self._add_path)
        button_layout.addWidget(add_path_btn)

        remove_path_btn = QPushButton(tr("settings.paths.remove_btn"))
        remove_path_btn.clicked.connect(self._remove_path)
        button_layout.addWidget(remove_path_btn)

        layout.addLayout(button_layout)
        layout.addStretch()

        widget.setLayout(layout)
        return widget

    def _create_urls_tab(self) -> QWidget:
        """Create URLs configuration tab."""
        widget = QWidget()
        layout = QVBoxLayout()

        layout.addWidget(QLabel(tr("settings.urls.label")))

        self.urls_list = QListWidget()
        for url in self.config.allowed_urls:
            self.urls_list.addItem(url)
        layout.addWidget(self.urls_list)

        button_layout = QHBoxLayout()

        add_url_btn = QPushButton(tr("settings.urls.add_btn"))
        add_url_btn.clicked.connect(self._add_url)
        button_layout.addWidget(add_url_btn)

        remove_url_btn = QPushButton(tr("settings.urls.remove_btn"))
        remove_url_btn.clicked.connect(self._remove_url)
        button_layout.addWidget(remove_url_btn)

        layout.addLayout(button_layout)
        layout.addStretch()

        widget.setLayout(layout)
        return widget

    def _create_logging_tab(self) -> QWidget:
        """Create logging configuration tab."""
        widget = QWidget()
        layout = QVBoxLayout()

        layout.addWidget(QLabel(tr("settings.logging.level_label")))
        self.log_level_combo: QComboBox = self._create_log_level_widget()
        layout.addWidget(self.log_level_combo)

        layout.addWidget(QLabel(tr("settings.logging.file_label")))
        log_file_layout = QHBoxLayout()

        self.log_file_input = QLineEdit()
        self.log_file_input.setText(str(self.config.log_file) if self.config.log_file else "")
        log_file_layout.addWidget(self.log_file_input)

        browse_btn = QPushButton(tr("settings.logging.browse_btn"))
        browse_btn.clicked.connect(self._browse_log_file)
        log_file_layout.addWidget(browse_btn)

        layout.addLayout(log_file_layout)
        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def _create_window_tab(self) -> QWidget:
        """Create window settings tab."""
        widget = QWidget()
        layout = QVBoxLayout()

        width_layout = QHBoxLayout()
        width_layout.addWidget(QLabel(tr("settings.window.width_label")))
        self.width_spin = QSpinBox()
        self.width_spin.setMinimum(400)
        self.width_spin.setMaximum(5000)
        self.width_spin.setValue(self.config.window_width)
        width_layout.addWidget(self.width_spin)
        width_layout.addStretch()
        layout.addLayout(width_layout)

        height_layout = QHBoxLayout()
        height_layout.addWidget(QLabel(tr("settings.window.height_label")))
        self.height_spin = QSpinBox()
        self.height_spin.setMinimum(300)
        self.height_spin.setMaximum(5000)
        self.height_spin.setValue(self.config.window_height)
        height_layout.addWidget(self.height_spin)
        height_layout.addStretch()
        layout.addLayout(height_layout)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def _create_profiles_tab(self) -> QWidget:
        """Create setups/import-export tab with clearer guidance."""
        widget = QWidget()
        layout = QVBoxLayout()

        saved_setups_label = QLabel(tr("settings.profiles.label"))
        saved_setups_label.setToolTip(tr("settings.profiles.label_tooltip"))
        layout.addWidget(saved_setups_label)

        self.profiles_help_label = QLabel(tr("settings.profiles.help_text"))
        self.profiles_help_label.setWordWrap(True)
        self.profiles_help_label.setStyleSheet("color: gray; font-size: 11px;")
        layout.addWidget(self.profiles_help_label)

        self.profiles_list = QListWidget()
        self.profiles_list.setToolTip(tr("settings.profiles.list_tooltip"))
        self._refresh_profiles_list()
        layout.addWidget(self.profiles_list)

        button_layout = QHBoxLayout()

        self.save_profile_btn = QPushButton(tr("settings.profiles.save_btn"))
        self.save_profile_btn.setToolTip(tr("settings.profiles.save_tooltip"))
        self.save_profile_btn.clicked.connect(self._save_profile)
        button_layout.addWidget(self.save_profile_btn)

        self.load_profile_btn = QPushButton(tr("settings.profiles.load_btn"))
        self.load_profile_btn.setToolTip(tr("settings.profiles.load_tooltip"))
        self.load_profile_btn.clicked.connect(self._load_profile)
        button_layout.addWidget(self.load_profile_btn)

        self.delete_profile_btn = QPushButton(tr("settings.profiles.delete_btn"))
        self.delete_profile_btn.setToolTip(tr("settings.profiles.delete_tooltip"))
        self.delete_profile_btn.clicked.connect(self._delete_profile)
        button_layout.addWidget(self.delete_profile_btn)

        layout.addLayout(button_layout)

        export_label = QLabel(tr("settings.profiles.transfer_label"))
        export_label.setToolTip(tr("settings.profiles.transfer_tooltip"))
        layout.addWidget(export_label)

        export_layout = QHBoxLayout()

        self.export_btn = QPushButton(tr("settings.profiles.export_btn"))
        self.export_btn.setToolTip(tr("settings.profiles.export_tooltip"))
        self.export_btn.clicked.connect(self._export_config)
        export_layout.addWidget(self.export_btn)

        self.import_btn = QPushButton(tr("settings.profiles.import_btn"))
        self.import_btn.setToolTip(tr("settings.profiles.import_tooltip"))
        self.import_btn.clicked.connect(self._import_config)
        export_layout.addWidget(self.import_btn)

        layout.addLayout(export_layout)
        layout.addStretch()

        widget.setLayout(layout)
        return widget

    def _create_log_level_widget(self) -> QComboBox:
        """Create log level selection widget."""
        combo = QComboBox()
        levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
        combo.addItems(levels)
        combo.setCurrentText(self.config.log_level)
        return combo

    def _add_path(self) -> None:
        """Add a new allowed path."""
        path = QFileDialog.getExistingDirectory(self, tr("settings.paths.select_dir_title"))
        if path:
            self.paths_list.addItem(path)

    def _remove_path(self) -> None:
        """Remove selected path."""
        if self.paths_list.currentItem():
            self.paths_list.takeItem(self.paths_list.row(self.paths_list.currentItem()))

    def _add_url(self) -> None:
        """Add a new allowed URL."""
        from PySide6.QtWidgets import QInputDialog

        url, ok = QInputDialog.getText(
            self, tr("settings.urls.add_title"), tr("settings.urls.add_prompt")
        )
        if ok and url:
            self.urls_list.addItem(url)

    def _remove_url(self) -> None:
        """Remove selected URL."""
        if self.urls_list.currentItem():
            self.urls_list.takeItem(self.urls_list.row(self.urls_list.currentItem()))

    def _browse_log_file(self) -> None:
        """Browse for log file location."""
        file_path, _ = QFileDialog.getSaveFileName(
            self,
            tr("settings.logging.select_file_title"),
            str(Path.home()),
            "Log Files (*.log);;All Files (*)",
        )
        if file_path:
            self.log_file_input.setText(file_path)

    def _refresh_profiles_list(self) -> None:
        """Refresh the list of available profiles."""
        self.profiles_list.clear()
        for profile_name in self.profile_manager.list_profiles():
            self.profiles_list.addItem(profile_name)

    def _save_profile(self) -> None:
        """Save current configuration as a profile."""
        from PySide6.QtWidgets import QInputDialog

        profile_name, ok = QInputDialog.getText(
            self, tr("settings.profiles.save_title"), tr("settings.profiles.save_prompt")
        )

        if ok and profile_name:
            try:
                self.profile_manager.save_profile(profile_name, self.config)
                self._refresh_profiles_list()
            except ConfigurationError as e:
                self._show_error(f"Failed to save profile: {e}")

    def _load_profile(self) -> None:
        """Load a saved profile."""
        current_item = self.profiles_list.currentItem()
        if not current_item:
            self._show_error(tr("settings.profiles.select_to_load"))
            return

        profile_name = current_item.text()
        try:
            config_data = self.profile_manager.load_profile(profile_name)
            self._apply_config_data(config_data)
        except ConfigurationError as e:
            self._show_error(f"Failed to load profile: {e}")

    def _delete_profile(self) -> None:
        """Delete a saved profile."""
        current_item = self.profiles_list.currentItem()
        if not current_item:
            self._show_error(tr("settings.profiles.select_to_delete"))
            return

        profile_name = current_item.text()
        try:
            self.profile_manager.delete_profile(profile_name)
            self._refresh_profiles_list()
        except ConfigurationError as e:
            self._show_error(f"Failed to delete profile: {e}")

    def _export_config(self) -> None:
        """Export configuration to file."""
        file_path, _ = QFileDialog.getSaveFileName(
            self,
            tr("settings.profiles.export_title"),
            str(Path.home()),
            "JSON Files (*.json);;All Files (*)",
        )

        if file_path:
            try:
                ConfigExporter.export_to_json(self.config, Path(file_path))
            except ConfigurationError as e:
                self._show_error(f"Failed to export configuration: {e}")

    def _import_config(self) -> None:
        """Import configuration from file."""
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            tr("settings.profiles.import_title"),
            str(Path.home()),
            "JSON Files (*.json);;All Files (*)",
        )

        if file_path:
            try:
                config_data = ConfigExporter.import_from_json(Path(file_path))
                self._apply_config_data(config_data)
            except ConfigurationError as e:
                self._show_error(f"Failed to import configuration: {e}")

    def _apply_config_data(self, config_data: Dict[str, Any]) -> None:
        """Apply imported configuration data to UI.

        Args:
            config_data: Configuration dictionary
        """
        self.paths_list.clear()
        for path in config_data.get("allowed_roots", []):
            self.paths_list.addItem(str(path))

        self.urls_list.clear()
        for url in config_data.get("allowed_urls", []):
            self.urls_list.addItem(url)

        self.log_level_combo.setCurrentText(config_data.get("log_level", "INFO"))
        log_file = config_data.get("log_file")
        self.log_file_input.setText(str(log_file) if log_file else "")

        self.width_spin.setValue(config_data.get("window_width", 800))
        self.height_spin.setValue(config_data.get("window_height", 600))

        language = config_data.get("language", "auto")
        idx = self.language_combo.findData(language)
        if idx >= 0:
            self.language_combo.setCurrentIndex(idx)

    def get_config_data(self) -> Dict[str, Any]:
        """Get updated configuration data from dialog.

        Returns:
            Configuration dictionary

        Raises:
            ConfigurationError: If configuration is invalid
        """
        url_mappings_table_count = (
            self.url_mappings_table.rowCount() if self.url_mappings_table else 0
        )

        config_data = {
            "app_name": self.config.app_name,
            "app_version": self.config.app_version,
            "language": self.language_combo.currentData(),
            "active_branding_id": self.branding_combo.currentData(),
            "log_level": self.log_level_combo.currentText(),
            "log_file": self.log_file_input.text() or None,
            "allowed_roots": [
                self.paths_list.item(i).text() for i in range(self.paths_list.count())
            ],
            "allowed_urls": [self.urls_list.item(i).text() for i in range(self.urls_list.count())],
            "webapp_url": self.webapp_url_input.text().strip(),
            "url_mappings": [
                {
                    "url_prefix": (
                        self.url_mappings_table.item(i, 0).text()  # type: ignore
                        if self.url_mappings_table.item(i, 0)
                        else ""
                    ),
                    "local_path": (
                        self.url_mappings_table.item(i, 1).text()  # type: ignore
                        if self.url_mappings_table.item(i, 1)
                        else ""
                    ),
                }
                for i in range(url_mappings_table_count)
            ],
            "window_width": self.width_spin.value(),
            "window_height": self.height_spin.value(),
            "enable_logging": self.config.enable_logging,
        }

        ConfigValidator.validate_or_raise(config_data)
        return config_data

    def _show_error(self, message: str) -> None:
        """Show error message to user.

        Args:
            message: Error message
        """
        from PySide6.QtWidgets import QMessageBox

        QMessageBox.critical(self, tr("dialog.error.title"), message)
