"""PySide2 GUI version of img2ico application."""

from __future__ import annotations

import logging
import os
import sys
from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any, ClassVar, Final

import PySide2
from PySide2.QtCore import QObject, Qt, QThread, Signal
from PySide2.QtWidgets import (
    QAction,
    QApplication,
    QComboBox,
    QFileDialog,
    QFormLayout,
    QGroupBox,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QMainWindow,
    QMessageBox,
    QProgressBar,
    QPushButton,
    QTextEdit,
    QVBoxLayout,
    QWidget,
)

# Import from img2ico module
try:
    from img2ico import ImageToIcoRunner, parse_sizes
except ImportError:
    try:
        from pytola.office.img2ico.img2ico import ImageToIcoRunner, parse_sizes
    except ImportError:
        from img2ico.img2ico import ImageToIcoRunner, parse_sizes

# Embedded QSS styles
EMBEDDED_STYLESHEET = """
/* Main window and global styles */
QMainWindow {
    background-color: #f8fafc;
    font-family: 'Microsoft YaHei UI', 'Segoe UI', sans-serif;
    font-size: 16px;
}

QWidget {
    font-family: 'Microsoft YaHei UI', 'Segoe UI', sans-serif;
    font-size: 16px;
    color: #0f172a;
}

/* Input panel styling */
#inputPanel {
    background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #f8fafc);
    border: 2px solid #e2e8f0;
    border-radius: 16px;
    margin: 0px;
    padding-top: 32px;
}

#inputPanel::title {
    subcontrol-origin: margin;
    subcontrol-position: top center;
    padding: 14px 22px;
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #3b82f6, stop:1 #1d4ed8);
    color: white;
    border-top-left-radius: 15px;
    border-top-right-radius: 15px;
    font-size: 18px;
    font-weight: 600;
}

/* Results panel styling */
#resultsPanel {
    background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #f8fafc);
    border: 2px solid #e2e8f0;
    border-radius: 16px;
    margin: 0px;
    padding-top: 32px;
}

#resultsPanel::title {
    subcontrol-origin: margin;
    subcontrol-position: top center;
    padding: 14px 22px;
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #3b82f6, stop:1 #1d4ed8);
    color: white;
    border-top-left-radius: 15px;
    border-top-right-radius: 15px;
    font-size: 18px;
    font-weight: 600;
}

/* Button styles */
QPushButton {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3b82f6, stop:1 #2563eb);
    color: white;
    border: none;
    border-radius: 8px;
    padding: 12px 20px;
    font-size: 15px;
    font-weight: 500;
    min-height: 36px;
}

QPushButton:hover {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #2563eb, stop:1 #1d4ed8);
}

QPushButton:pressed {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #1d4ed8, stop:1 #1e40af);
}

QPushButton:disabled {
    background: #94a3b8;
    color: #cbd5e1;
}

#convert_btn {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #22c55e, stop:1 #16a34a);
    padding: 14px 32px;
    font-size: 17px;
    font-weight: 700;
}

#convert_btn:hover {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #16a34a, stop:1 #15803d);
}

#convert_btn:pressed {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #15803d, stop:1 #166534);
}

#convert_btn:disabled {
    background: #d1d5db;
    color: #6b7280;
}

/* Input controls styles */
QLineEdit {
    background-color: #ffffff;
    border: 2px solid #cbd5e1;
    border-radius: 8px;
    padding: 12px 16px;
    font-size: 16px;
    color: #0f172a;
    min-height: 28px;
}

QLineEdit:focus {
    border: 2px solid #3b82f6;
    background-color: #f8fafc;
}

QComboBox {
    background-color: #ffffff;
    border: 2px solid #cbd5e1;
    border-radius: 8px;
    padding: 10px 14px;
    font-size: 15px;
    min-height: 28px;
}

QComboBox:hover {
    border: 2px solid #94a3b8;
}

QComboBox:focus {
    border: 2px solid #3b82f6;
}

QSpinBox {
    background-color: #ffffff;
    border: 2px solid #cbd5e1;
    border-radius: 8px;
    padding: 10px 14px;
    font-size: 15px;
    min-height: 28px;
}

QSpinBox:hover {
    border: 2px solid #94a3b8;
}

QSpinBox:focus {
    border: 2px solid #3b82f6;
}

/* Progress bar styling */
QProgressBar {
    border: 2px solid #cbd5e1;
    border-radius: 10px;
    text-align: center;
    font-size: 14px;
    font-weight: 600;
    background-color: #f1f5f9;
    min-height: 28px;
}

QProgressBar::chunk {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #3b82f6, stop:1 #2563eb);
    border-radius: 8px;
}

/* Log text area styling */
QTextEdit {
    background-color: #f8fafc;
    border: 2px solid #cbd5e1;
    border-radius: 8px;
    padding: 12px 16px;
    font-family: 'Consolas', monospace;
    font-size: 14px;
}
"""

logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)

# Constants
_MIN_WINDOW_SIZE: Final[tuple[int, int]] = (900, 800)
DEFAULT_WINDOW_WIDTH: Final[int] = 1000  # Increased from 900
DEFAULT_WINDOW_HEIGHT: Final[int] = 800  # Increased from 600
DEFAULT_WINDOW_X: Final[int] = 100
DEFAULT_WINDOW_Y: Final[int] = 100
MAX_RECENT_ITEMS: Final[int] = 10

# UI Styling Constants
UI_LABEL_MIN_WIDTH: Final[int] = 130
UI_INPUT_MIN_HEIGHT: Final[int] = 40  # Increased from 36
UI_BUTTON_MIN_HEIGHT: Final[int] = 36  # Increased from 32
UI_LAYOUT_SPACING: Final[int] = 16  # Increased from 12
UI_LAYOUT_MARGIN: Final[int] = 25  # Increased from 20

# Setup Qt plugin path
qt_dir = Path(PySide2.__file__).parent
plugin_path = str(qt_dir / "plugins" / "platforms")
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = plugin_path


@dataclass
class Img2IcoConfig:
    """Image to ICO GUI configuration with persistence support."""

    input_path: str = str(Path.cwd())
    output_path: str = ""
    sizes: str = "16,24,32,48,64,128,256,512,1024"
    quality: str = "high"
    window_width: int = DEFAULT_WINDOW_WIDTH
    window_height: int = DEFAULT_WINDOW_HEIGHT
    window_x: int = DEFAULT_WINDOW_X
    window_y: int = DEFAULT_WINDOW_Y
    recent_input_paths: list[str] = field(default_factory=list)
    recent_output_paths: list[str] = field(default_factory=list)

    def __post_init__(self) -> None:
        """Initialize configuration after creation."""
        if self.recent_input_paths is None:
            self.recent_input_paths = []
        if self.recent_output_paths is None:
            self.recent_output_paths = []


@dataclass
class ConfigManager:
    """Manage GUI configuration persistence."""

    MAX_RECENT_ITEMS: ClassVar[int] = MAX_RECENT_ITEMS
    DEFAULT_CONFIG: ClassVar[Img2IcoConfig] = Img2IcoConfig()

    config_file: Path = field(
        default_factory=lambda: Path.home() / ".pytola" / "img2ico_gui.json",
    )
    config: Img2IcoConfig = field(init=False)

    def __post_init__(self) -> None:
        """Initialize configuration manager."""
        self.config = self._load_config()

    def _load_config(self) -> Img2IcoConfig:
        """Load configuration from file."""
        import json

        if self.config_file.exists():
            try:
                with Path(self.config_file).open(encoding="utf-8") as f:
                    config_data = json.load(f)

                return Img2IcoConfig(
                    input_path=config_data.get(
                        "input_path",
                        self.DEFAULT_CONFIG.input_path,
                    ),
                    output_path=config_data.get(
                        "output_path",
                        self.DEFAULT_CONFIG.output_path,
                    ),
                    sizes=config_data.get("sizes", self.DEFAULT_CONFIG.sizes),
                    quality=config_data.get("quality", self.DEFAULT_CONFIG.quality),
                    window_width=config_data.get(
                        "window_width",
                        self.DEFAULT_CONFIG.window_width,
                    ),
                    window_height=config_data.get(
                        "window_height",
                        self.DEFAULT_CONFIG.window_height,
                    ),
                    window_x=config_data.get("window_x", self.DEFAULT_CONFIG.window_x),
                    window_y=config_data.get("window_y", self.DEFAULT_CONFIG.window_y),
                    recent_input_paths=config_data.get("recent_input_paths", []),
                    recent_output_paths=config_data.get("recent_output_paths", []),
                )
            except Exception as e:
                logger.warning(f"Failed to load config: {e}. Using defaults.")
        return Img2IcoConfig()

    def save_config(self) -> None:
        """Save configuration to file."""
        import json

        try:
            self.config_file.parent.mkdir(parents=True, exist_ok=True)
            config_dict = {
                "input_path": self.config.input_path,
                "output_path": self.config.output_path,
                "sizes": self.config.sizes,
                "quality": self.config.quality,
                "window_width": self.config.window_width,
                "window_height": self.config.window_height,
                "window_x": self.config.window_x,
                "window_y": self.config.window_y,
                "recent_input_paths": self.config.recent_input_paths,
                "recent_output_paths": self.config.recent_output_paths,
            }
            with Path(self.config_file).open("w", encoding="utf-8") as f:
                json.dump(config_dict, f, indent=2, ensure_ascii=False)
        except Exception as e:
            logger.warning(f"Failed to save config: {e}")

    def get(self, key: str, default: Any = None) -> Any:
        """Get configuration value."""
        return getattr(self.config, key, default)

    def set(self, key: str, value: Any) -> None:
        """Set configuration value."""
        if hasattr(self.config, key):
            setattr(self.config, key, value)

    def add_recent_path(self, path_list: list[str], new_path: str) -> list[str]:
        """Add path to recent paths list."""
        filtered = [p for p in path_list if p != new_path]
        filtered.insert(0, new_path)
        return filtered[: self.MAX_RECENT_ITEMS]


class WorkerSignals(QObject):
    """Signals for worker thread."""

    progress_message = Signal(str)
    progress_update = Signal(int, int)
    finished = Signal(dict)
    error = Signal(str)


class ConversionWorker(QThread):
    """Worker thread for running image conversion in background."""

    def __init__(
        self,
        input_path: Path,
        output_path: Path | None,
        sizes: set[int],
        quality: str,
    ) -> None:
        """Initialize worker thread."""
        super().__init__()
        self.input_path = input_path
        self.output_path = output_path
        self.sizes = sizes
        self.quality = quality
        self.signals = WorkerSignals()

    def run(self) -> None:
        """Run the image conversion."""
        try:
            self.signals.progress_message.emit("Starting conversion...")

            runner = ImageToIcoRunner(
                input_path=self.input_path,
                output_path=self.output_path,
                sizes=self.sizes,
                quality=self.quality,
            )

            # Handle single file vs directory
            if self.input_path.is_file():
                runner.run()
                result = {
                    "success": True,
                    "files_processed": 1,
                    "output_path": str(self.output_path)
                    if self.output_path
                    else str(self.input_path.with_suffix(".ico")),
                }
            else:
                # Directory conversion
                image_files = runner.image_files
                total = len(image_files)

                if total == 0:
                    msg = "No valid image files found in directory"
                    raise ValueError(msg)

                self.signals.progress_message.emit(f"Found {total} image files")

                for i, img_file in enumerate(image_files):
                    self.signals.progress_message.emit(f"Converting {img_file.name}...")
                    self.signals.progress_update.emit(i + 1, total)

                runner.run()

                result = {
                    "success": True,
                    "files_processed": total,
                    "output_path": str(self.output_path) if self.output_path else str(self.input_path / "ico_output"),
                }

            self.signals.progress_message.emit("Conversion completed!")
            self.signals.finished.emit(result)

        except Exception as e:
            self.signals.error.emit(str(e))


class Img2IcoGUI(QMainWindow):
    """Main GUI window for img2ico application."""

    def __init__(self) -> None:
        """Initialize GUI components."""
        super().__init__()
        self.config_manager = ConfigManager()
        self.conversion_worker = None
        self.is_converting = False
        self.init_ui()
        self._load_config()

    def init_ui(self) -> None:
        """Initialize user interface."""
        self.setWindowTitle("Image to ICO Converter")
        self.setMinimumSize(*_MIN_WINDOW_SIZE)  # Increased minimum size

        # Apply stylesheet
        self.setStyleSheet(EMBEDDED_STYLESHEET)

        # Create central widget
        central_widget = QWidget()
        central_widget.setObjectName("centralWidget")
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        main_layout.setSpacing(25)  # Increased from 20
        main_layout.setContentsMargins(30, 30, 30, 30)  # Increased from 25

        # Create menu bar
        self._create_menu_bar()

        # Create sections
        self._create_input_section(main_layout)
        self._create_options_section(main_layout)
        self._create_actions_section(main_layout)
        self._create_results_section(main_layout)

    def _create_menu_bar(self) -> None:
        """Create menu bar."""
        menubar = self.menuBar()

        # File menu
        file_menu = menubar.addMenu("&File")

        exit_action = QAction("E&xit", self)
        exit_action.triggered.connect(self.close)  # type: ignore
        exit_action.setShortcut("Ctrl+Q")
        file_menu.addAction(exit_action)

        # Help menu
        help_menu = menubar.addMenu("&Help")

        about_action = QAction("&About", self)
        about_action.triggered.connect(self._show_about)  # type: ignore
        help_menu.addAction(about_action)

    def _create_input_section(self, parent_layout: QVBoxLayout) -> None:
        """Create input configuration section."""
        input_group = QGroupBox("Input Configuration")
        input_group.setObjectName("inputPanel")
        input_layout = QVBoxLayout()
        input_layout.setSpacing(22)  # Increased from 18
        input_layout.setContentsMargins(25, 25, 25, 25)  # Increased from 20
        input_group.setLayout(input_layout)

        # Input path
        input_path_layout = QHBoxLayout()
        input_path_layout.setSpacing(12)  # Increased from 10
        self.input_label = QLabel("Input:")
        self.input_label.setMinimumWidth(UI_LABEL_MIN_WIDTH)
        self.input_edit = QLineEdit(str(Path.cwd()))
        self.input_edit.setMinimumHeight(UI_INPUT_MIN_HEIGHT)
        input_browse_btn = QPushButton("Browse...")
        input_browse_btn.setMinimumHeight(UI_BUTTON_MIN_HEIGHT)
        input_browse_btn.clicked.connect(self._browse_input)  # type: ignore
        input_path_layout.addWidget(self.input_label)
        input_path_layout.addWidget(self.input_edit, 1)
        input_path_layout.addWidget(input_browse_btn)
        input_layout.addLayout(input_path_layout)

        # Output path
        output_path_layout = QHBoxLayout()
        output_path_layout.setSpacing(12)  # Increased from 10
        self.output_label = QLabel("Output:")
        self.output_label.setMinimumWidth(UI_LABEL_MIN_WIDTH)
        self.output_edit = QLineEdit()
        self.output_edit.setPlaceholderText("Optional - defaults to input location")
        self.output_edit.setMinimumHeight(UI_INPUT_MIN_HEIGHT)
        output_browse_btn = QPushButton("Browse...")
        output_browse_btn.setMinimumHeight(UI_BUTTON_MIN_HEIGHT)
        output_browse_btn.clicked.connect(self._browse_output)  # type: ignore
        output_path_layout.addWidget(self.output_label)
        output_path_layout.addWidget(self.output_edit, 1)
        output_path_layout.addWidget(output_browse_btn)
        input_layout.addLayout(output_path_layout)

        parent_layout.addWidget(input_group)

    def _create_options_section(self, parent_layout: QVBoxLayout) -> None:
        """Create conversion options section."""
        options_group = QGroupBox("Conversion Options")
        options_layout = QFormLayout()
        options_layout.setSpacing(22)  # Increased from 18
        options_layout.setContentsMargins(25, 25, 25, 25)  # Increased from 20
        options_layout.setVerticalSpacing(22)  # Increased from 18
        options_layout.setHorizontalSpacing(12)  # Increased from 10
        options_group.setLayout(options_layout)

        # Icon sizes
        self.sizes_edit = QLineEdit("16,24,32,48,64,128,256,512,1024")
        self.sizes_edit.setPlaceholderText("Comma-separated sizes (e.g., 16,32,64)")
        self.sizes_edit.setMinimumHeight(UI_INPUT_MIN_HEIGHT)
        options_layout.addRow("Icon Sizes:", self.sizes_edit)

        # Quality
        self.quality_combo = QComboBox()
        self.quality_combo.addItems(["high", "medium", "low"])
        self.quality_combo.setMinimumHeight(UI_INPUT_MIN_HEIGHT)
        options_layout.addRow("Quality:", self.quality_combo)

        parent_layout.addWidget(options_group)

    def _create_actions_section(self, parent_layout: QVBoxLayout) -> None:
        """Create action buttons section."""
        actions_layout = QHBoxLayout()
        actions_layout.setSpacing(12)
        actions_layout.setContentsMargins(
            0,
            10,
            0,
            10,
        )  # Add vertical spacing around button

        self.convert_btn = QPushButton("Convert to ICO")
        self.convert_btn.setObjectName("convert_btn")
        self.convert_btn.clicked.connect(self._start_conversion)  # type: ignore
        self.convert_btn.setMinimumHeight(52)  # Increased from 48
        self.convert_btn.setCursor(Qt.PointingHandCursor)

        actions_layout.addWidget(self.convert_btn)
        parent_layout.addLayout(actions_layout)

    def _create_results_section(self, parent_layout: QVBoxLayout) -> None:
        """Create results display section."""
        results_group = QGroupBox("Results")
        results_group.setObjectName("resultsPanel")
        results_layout = QVBoxLayout()
        results_layout.setSpacing(18)  # Increased from 15
        results_layout.setContentsMargins(25, 25, 25, 25)  # Increased from 20
        results_group.setLayout(results_layout)

        # Progress bar
        self.progress_bar = QProgressBar()
        self.progress_bar.setMinimum(0)
        self.progress_bar.setMaximum(100)
        self.progress_bar.setValue(0)
        self.progress_bar.setMinimumHeight(32)  # Increased height
        results_layout.addWidget(self.progress_bar)

        # Log text
        self.log_label = QLabel("Progress Log:")
        results_layout.addWidget(self.log_label)
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        self.log_text.setMaximumHeight(220)  # Increased from 200
        results_layout.addWidget(self.log_text)

        parent_layout.addWidget(results_group)

    def _browse_input(self) -> None:
        """Browse for input file or directory."""
        # Try both file and directory dialogs
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            "Select Input Image",
            self.input_edit.text() or str(Path.cwd()),
            "Images (*.png *.jpg *.jpeg *.gif *.bmp *.webp *.tiff *.svg);;All Files (*.*)",
        )

        if file_path:
            self.input_edit.setText(str(Path(file_path)))
            return

        # If no file selected, try directory
        dir_path = QFileDialog.getExistingDirectory(
            self,
            "Select Input Directory",
            self.input_edit.text() or str(Path.cwd()),
        )

        if dir_path:
            self.input_edit.setText(str(Path(dir_path)))

    def _browse_output(self) -> None:
        """Browse for output file or directory."""
        input_path = Path(self.input_edit.text())

        if input_path.is_file():
            # Single file input - output is also a file
            file_path, _ = QFileDialog.getSaveFileName(
                self,
                "Select Output ICO File",
                str(input_path.with_suffix(".ico")),
                "ICO Files (*.ico)",
            )
            if file_path:
                self.output_edit.setText(str(Path(file_path)))
        else:
            # Directory input - output is also a directory
            dir_path = QFileDialog.getExistingDirectory(
                self,
                "Select Output Directory",
                self.output_edit.text() or str(Path.cwd() / "ico_output"),
            )
            if dir_path:
                self.output_edit.setText(str(Path(dir_path)))

    def _start_conversion(self) -> None:
        """Start the image conversion."""
        # Validate input
        input_path = Path(self.input_edit.text())
        if not input_path.exists():
            QMessageBox.warning(self, "Error", "Input path does not exist!")
            return

        # Parse sizes
        try:
            sizes = parse_sizes(self.sizes_edit.text())
        except ValueError as e:
            QMessageBox.warning(self, "Error", f"Invalid sizes format: {e}")
            return

        # Get output path
        output_path = None
        if self.output_edit.text().strip():
            output_path = Path(self.output_edit.text())

        # Clear previous results
        self.log_text.clear()
        self.progress_bar.setValue(0)

        # Disable convert button
        self.is_converting = True
        self.convert_btn.setEnabled(False)

        # Create and start worker
        quality = self.quality_combo.currentText()
        self.conversion_worker = ConversionWorker(
            input_path,
            output_path,
            sizes,
            quality,
        )
        self.conversion_worker.signals.progress_message.connect(self._log_message)
        self.conversion_worker.signals.progress_update.connect(self._update_progress)
        self.conversion_worker.signals.finished.connect(self._conversion_finished)
        self.conversion_worker.signals.error.connect(self._conversion_error)
        self.conversion_worker.start()

    def _conversion_finished(self, result: dict[str, Any]) -> None:
        """Handle conversion completion."""
        self.is_converting = False
        self.convert_btn.setEnabled(True)
        self.progress_bar.setValue(100)

        files_count = result.get("files_processed", 0)
        output_path = result.get("output_path", "")

        self._log_message(f"Successfully converted {files_count} file(s)")
        self._log_message(f"Output location: {output_path}")

        QMessageBox.information(
            self,
            "Success",
            f"Conversion completed!\n{files_count} file(s) converted to ICO format.",
        )

        # Save configuration
        self._save_config()

    def _conversion_error(self, error_msg: str) -> None:
        """Handle conversion error."""
        self.is_converting = False
        self.convert_btn.setEnabled(True)
        self._log_message(f"Error: {error_msg}")
        QMessageBox.critical(self, "Error", f"Conversion failed: {error_msg}")

    def _update_progress(self, current: int, total: int) -> None:
        """Update progress bar."""
        if total > 0:
            percentage = int((current / total) * 100)
            self.progress_bar.setValue(percentage)
            QApplication.processEvents()

    def _log_message(self, message: str) -> None:
        """Add message to log."""
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.append(f"[{timestamp}] {message}")
        QApplication.processEvents()

    def _load_config(self) -> None:
        """Load configuration and restore UI state."""
        # Restore window size and position
        width = self.config_manager.get("window_width", DEFAULT_WINDOW_WIDTH)
        height = self.config_manager.get("window_height", DEFAULT_WINDOW_HEIGHT)
        x = self.config_manager.get("window_x", DEFAULT_WINDOW_X)
        y = self.config_manager.get("window_y", DEFAULT_WINDOW_Y)
        self.resize(width, height)
        self.move(x, y)

        # Restore paths
        input_path = self.config_manager.get("input_path", str(Path.cwd()))
        self.input_edit.setText(input_path)

        output_path = self.config_manager.get("output_path", "")
        self.output_edit.setText(output_path)

        # Restore options
        sizes = self.config_manager.get("sizes", "16,24,32,48,64,128,256,512,1024")
        self.sizes_edit.setText(sizes)

        quality = self.config_manager.get("quality", "high")
        index = self.quality_combo.findText(quality)
        if index >= 0:
            self.quality_combo.setCurrentIndex(index)

    def _save_config(self) -> None:
        """Save current UI state to configuration."""
        # Save window size and position
        self.config_manager.set("window_width", self.width())
        self.config_manager.set("window_height", self.height())
        self.config_manager.set("window_x", self.x())
        self.config_manager.set("window_y", self.y())

        # Save paths
        input_path = self.input_edit.text()
        self.config_manager.set("input_path", input_path)

        recent_inputs = self.config_manager.get("recent_input_paths", [])
        recent_inputs = self.config_manager.add_recent_path(recent_inputs, input_path)
        self.config_manager.set("recent_input_paths", recent_inputs)

        output_path = self.output_edit.text()
        self.config_manager.set("output_path", output_path)

        if output_path:
            recent_outputs = self.config_manager.get("recent_output_paths", [])
            recent_outputs = self.config_manager.add_recent_path(
                recent_outputs,
                output_path,
            )
            self.config_manager.set("recent_output_paths", recent_outputs)

        # Save options
        self.config_manager.set("sizes", self.sizes_edit.text())
        self.config_manager.set("quality", self.quality_combo.currentText())

        # Persist to file
        self.config_manager.save_config()

    def _show_about(self) -> None:
        """Show about dialog."""
        QMessageBox.about(
            self,
            "About Image to ICO Converter",
            "Image to ICO Converter GUI\n\nVersion 1.0\n\nConvert images to multi-size ICO format",
        )

    def closeEvent(self, event) -> None:
        """Handle window close event."""
        self._save_config()
        event.accept()


def main() -> None:
    """Run main entry point for the img2ico GUI application."""
    app = QApplication(sys.argv)
    app.setApplicationName("Image to ICO Converter")

    window = Img2IcoGUI()
    window.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
