"""Structural configuration page."""

from __future__ import annotations

import contextlib
from typing import Any

from qgis.core import QgsMapLayerProxyModel
from qgis.gui import QgsDoubleSpinBox, QgsFieldComboBox, QgsMapLayerComboBox
from qgis.PyQt.QtCore import QCoreApplication, pyqtSignal
from qgis.PyQt.QtWidgets import QGridLayout, QLabel

from sec_interp.core.validation.project_validator import (
    ProjectValidator,
    ValidationParams,
)
from sec_interp.gui.main_dialog_config import DialogDefaults

from .base_page import BasePage


class StructurePage(BasePage):
    """Configuration page for Structural Measurements."""

    dataChanged = pyqtSignal()

    def __init__(self, parent: Any = None) -> None:
        """Initialize the structure configuration page.

        Args:
            parent: Optional parent widget.

        """
        super().__init__(
            QCoreApplication.translate("StructurePage", "Structural Measurements"),
            parent,
        )

    def _setup_ui(self) -> None:
        super()._setup_ui()

        self.group_layout = QGridLayout(self.group_box)
        self.group_layout.setSpacing(6)

        # Row 0: Structural Layer
        self.group_layout.addWidget(QLabel(self.tr("Structural Layer")), 0, 0)

        self.layer_combo = QgsMapLayerComboBox()

        # Use modern flags if available (QGIS 3.32+)
        try:
            from qgis.core import Qgis  # noqa: PLC0415

            self.layer_combo.setFilters(Qgis.LayerFilters(Qgis.LayerFilter.PointLayer))
        except (ImportError, AttributeError, TypeError):
            self.layer_combo.setFilters(QgsMapLayerProxyModel.PointLayer)

        self.layer_combo.setAllowEmptyLayer(True)
        self.layer_combo.setToolTip(self.tr("Select the point layer with structural measurements"))
        self.layer_combo.setCurrentIndex(0)
        self.group_layout.addWidget(self.layer_combo, 0, 1)

        # Row 1: Dip Field
        self.group_layout.addWidget(QLabel(self.tr("Dip Field")), 1, 0)

        self.dip_combo = QgsFieldComboBox()
        self.dip_combo.setToolTip(self.tr("Select field with dip values (0-90)"))
        self.group_layout.addWidget(self.dip_combo, 1, 1)

        # Row 2: Strike Field
        self.group_layout.addWidget(QLabel(self.tr("Strike Field")), 2, 0)

        self.strike_combo = QgsFieldComboBox()
        self.strike_combo.setToolTip(self.tr("Select field with strike values (0-360)"))
        self.group_layout.addWidget(self.strike_combo, 2, 1)

        # Row 3: Dip Line Scale
        self.group_layout.addWidget(QLabel(self.tr("Dip Line Scale")), 3, 0)

        self.scale_spin = QgsDoubleSpinBox()
        self.scale_spin.setRange(0.1, 100.0)
        self.scale_spin.setValue(float(DialogDefaults.DIP_SCALE_FACTOR))
        self.scale_spin.setSingleStep(0.5)
        self.scale_spin.setToolTip(self.tr("Length factor for drawing dip lines"))
        self.group_layout.addWidget(self.scale_spin, 3, 1)

        # Connections: update fields when layer changes
        self.layer_combo.layerChanged.connect(self._on_layer_changed)

        # Emit dataChanged when selections change
        self.layer_combo.layerChanged.connect(self.dataChanged.emit)
        self.dip_combo.fieldChanged.connect(self.dataChanged.emit)
        self.strike_combo.fieldChanged.connect(self.dataChanged.emit)

    def _on_layer_changed(self, layer: Any) -> None:
        """Update both field combos when layer changes."""
        self.dip_combo.setLayer(layer)
        self.strike_combo.setLayer(layer)

    def get_data(self) -> dict[str, Any]:
        """Get structural configuration."""
        return {
            "structural_layer": self.layer_combo.currentLayer(),
            "dip_field": self.dip_combo.currentField(),
            "strike_field": self.strike_combo.currentField(),
            "dip_scale_factor": self.scale_spin.value(),
        }

    def is_complete(self) -> bool:
        """Check if required fields are filled if a layer is selected."""
        data = self.get_data()
        params = ValidationParams(
            struct_layer=data["structural_layer"],
            struct_dip_field=data["dip_field"],
            struct_strike_field=data["strike_field"],
        )
        return ProjectValidator.is_structure_complete(params)

    def disconnect_signals(self) -> None:
        """Disconnect all signals to prevent memory leaks."""
        try:
            self.layer_combo.layerChanged.disconnect(self._on_layer_changed)
            self.layer_combo.layerChanged.disconnect(self.dataChanged.emit)
        except (TypeError, RuntimeError):
            pass
        with contextlib.suppress(TypeError, RuntimeError):
            self.dip_combo.fieldChanged.disconnect(self.dataChanged.emit)
        with contextlib.suppress(TypeError, RuntimeError):
            self.strike_combo.fieldChanged.disconnect(self.dataChanged.emit)
        with contextlib.suppress(TypeError, RuntimeError):
            self.dataChanged.disconnect()
