"""Configuration panel widget for GUI."""

from __future__ import annotations

from pathlib import Path
from typing import Any

from PySide2.QtCore import Qt
from PySide2.QtWidgets import (
    QCheckBox,
    QComboBox,
    QFileDialog,
    QFormLayout,
    QGroupBox,
    QHBoxLayout,
    QLineEdit,
    QPushButton,
    QSpinBox,
    QWidget,
)

from ...core.config import ArchiveFormat, LoaderType, MirrorSource
from .build_worker import BuildWorker


class ConfigPanel(QWidget):
    """Configuration panel for build settings."""

    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        self.build_worker: BuildWorker | None = None
        self._setup_ui()

    def _setup_ui(self) -> None:
        """Set up the configuration panel UI."""
        layout = QFormLayout(self)
        layout.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)

        # Project settings group
        project_group = QGroupBox("Project Settings")
        project_layout = QFormLayout(project_group)

        # Directory selection
        self.dir_edit = QLineEdit(str(Path.cwd()))
        dir_button = QPushButton("Browse...")
        dir_button.clicked.connect(self._browse_directory)

        dir_layout = QHBoxLayout()
        dir_layout.addWidget(self.dir_edit)
        dir_layout.addWidget(dir_button)
        project_layout.addRow("Project Directory:", dir_layout)

        # Project name
        self.project_name_edit = QLineEdit()
        project_layout.addRow("Project Name:", self.project_name_edit)

        layout.addRow(project_group)

        # Build settings group
        build_group = QGroupBox("Build Settings")
        build_layout = QFormLayout(build_group)

        # Python version
        self.python_version_edit = QLineEdit("3.8.10")
        build_layout.addRow("Python Version:", self.python_version_edit)

        # Loader type
        self.loader_type_combo = QComboBox()
        self.loader_type_combo.addItems([lt.value for lt in LoaderType])
        build_layout.addRow("Loader Type:", self.loader_type_combo)

        # Entry suffix
        self.entry_suffix_edit = QLineEdit(".ent")
        build_layout.addRow("Entry Suffix:", self.entry_suffix_edit)

        # Generate loader
        self.generate_loader_check = QCheckBox()
        self.generate_loader_check.setChecked(True)
        build_layout.addRow("Generate Loader:", self.generate_loader_check)

        # Offline mode
        self.offline_check = QCheckBox()
        build_layout.addRow("Offline Mode:", self.offline_check)

        # Max concurrent tasks
        self.max_concurrent_spin = QSpinBox()
        self.max_concurrent_spin.setRange(1, 16)
        self.max_concurrent_spin.setValue(4)
        build_layout.addRow("Max Concurrent Tasks:", self.max_concurrent_spin)

        # Debug mode
        self.debug_check = QCheckBox()
        build_layout.addRow("Debug Mode:", self.debug_check)

        layout.addRow(build_group)

        # Advanced settings group
        advanced_group = QGroupBox("Advanced Settings")
        advanced_layout = QFormLayout(advanced_group)

        # Cache directory
        self.cache_dir_edit = QLineEdit()
        cache_button = QPushButton("Browse...")
        cache_button.clicked.connect(self._browse_cache_directory)

        cache_layout = QHBoxLayout()
        cache_layout.addWidget(self.cache_dir_edit)
        cache_layout.addWidget(cache_button)
        advanced_layout.addRow("Cache Directory:", cache_layout)

        # Archive format
        self.archive_format_combo = QComboBox()
        self.archive_format_combo.addItems([af.value for af in ArchiveFormat])
        advanced_layout.addRow("Archive Format:", self.archive_format_combo)

        # PyPI mirror
        self.mirror_combo = QComboBox()
        self.mirror_combo.addItems([ms.value for ms in MirrorSource])
        self.mirror_combo.setCurrentText(MirrorSource.ALIYUN.value)
        advanced_layout.addRow("PyPI Mirror:", self.mirror_combo)

        # Archive type
        self.archive_type_combo = QComboBox()
        self.archive_type_combo.addItems(
            [
                "",
                "zip",
                "tar",
                "gztar",
                "bztar",
                "xztar",
                "7z",
                "nsis",
            ]
        )
        advanced_layout.addRow("Create Archive:", self.archive_type_combo)

        layout.addRow(advanced_group)

    def _browse_directory(self) -> None:
        """Open directory selection dialog for project directory."""
        current_path = self.dir_edit.text()
        directory = QFileDialog.getExistingDirectory(
            self,
            "Select Project Directory",
            current_path,
            QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks,
        )
        if directory:
            self.dir_edit.setText(directory)
            # Auto-detect project name
            self._auto_detect_project_name(directory)

    def _browse_cache_directory(self) -> None:
        """Open directory selection dialog for cache directory."""
        current_path = self.cache_dir_edit.text()
        directory = QFileDialog.getExistingDirectory(
            self,
            "Select Cache Directory",
            current_path,
            QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks,
        )
        if directory:
            self.cache_dir_edit.setText(directory)

    def _auto_detect_project_name(self, directory_path: str) -> None:
        """Auto-detect project name from directory."""
        try:
            dir_path = Path(directory_path)
            if not dir_path.exists() or not dir_path.is_dir():
                return

            project_name = dir_path.name

            # Try to read pyproject.toml
            pyproject_file = dir_path / "pyproject.toml"
            if pyproject_file.exists():
                try:
                    import tomli

                    with pyproject_file.open("rb") as f:
                        pyproject_data = tomli.load(f)

                    # Try to get project name from pyproject.toml
                    if "project" in pyproject_data:
                        project_name = pyproject_data["project"].get("name", project_name)
                    elif "tool" in pyproject_data and "poetry" in pyproject_data["tool"]:
                        project_name = pyproject_data["tool"]["poetry"].get("name", project_name)
                except Exception:
                    pass

            self.project_name_edit.setText(project_name)
        except Exception:
            pass

    def get_config_data(self) -> dict[str, Any]:
        """Get current configuration data."""
        return {
            "directory": self.dir_edit.text(),
            "project_name": self.project_name_edit.text() or None,
            "python_version": self.python_version_edit.text(),
            "loader_type": self.loader_type_combo.currentText(),
            "entry_suffix": self.entry_suffix_edit.text(),
            "generate_loader": self.generate_loader_check.isChecked(),
            "offline": self.offline_check.isChecked(),
            "max_concurrent": self.max_concurrent_spin.value(),
            "debug": self.debug_check.isChecked(),
            "cache_dir": self.cache_dir_edit.text() or None,
            "archive_format": self.archive_format_combo.currentText(),
            "mirror": self.mirror_combo.currentText(),
            "archive_type": self.archive_type_combo.currentText() or None,
        }

    def set_config_data(self, config_data: dict[str, Any]) -> None:
        """Set configuration data."""
        if "directory" in config_data:
            self.dir_edit.setText(str(config_data["directory"]))
        if "project_name" in config_data:
            self.project_name_edit.setText(config_data["project_name"] or "")
        if "python_version" in config_data:
            self.python_version_edit.setText(config_data["python_version"])
        if "loader_type" in config_data:
            index = self.loader_type_combo.findText(config_data["loader_type"])
            if index >= 0:
                self.loader_type_combo.setCurrentIndex(index)
        if "entry_suffix" in config_data:
            self.entry_suffix_edit.setText(config_data["entry_suffix"])
        if "generate_loader" in config_data:
            self.generate_loader_check.setChecked(config_data["generate_loader"])
        if "offline" in config_data:
            self.offline_check.setChecked(config_data["offline"])
        if "max_concurrent" in config_data:
            self.max_concurrent_spin.setValue(config_data["max_concurrent"])
        if "debug" in config_data:
            self.debug_check.setChecked(config_data["debug"])
        if "cache_dir" in config_data:
            self.cache_dir_edit.setText(config_data["cache_dir"] or "")
        if "archive_format" in config_data:
            index = self.archive_format_combo.findText(config_data["archive_format"])
            if index >= 0:
                self.archive_format_combo.setCurrentIndex(index)
        if "mirror" in config_data:
            index = self.mirror_combo.findText(config_data["mirror"])
            if index >= 0:
                self.mirror_combo.setCurrentIndex(index)
        if "archive_type" in config_data:
            index = self.archive_type_combo.findText(config_data["archive_type"] or "")
            if index >= 0:
                self.archive_type_combo.setCurrentIndex(index)
