"""Pick a published model version from the central registry (provenance item 6).

A read-only QDialog that lists the versions in a per-kind registry DB (the same
DBs ArcGIS Pro and the editors use) and returns the chosen ``RegistryVersion``.

The pure-Python registry logic lives in ``..model_registry`` (no Qt). This dialog
is the thin Qt surface; tests exercise the pure module instead, so the Qt/PyQt
imports here stay out of the QGIS-free unit tests.
"""

from __future__ import annotations

from typing import List, Optional

from ..qt_compat import (
    QAbstractItemView,
    QDialog,
    QDialogButtonBox,
    QHBoxLayout,
    QHeaderView,
    QLabel,
    QMessageBox,
    QPushButton,
    QTableWidget,
    QTableWidgetItem,
    QVBoxLayout,
    Qt,
    exec_dialog,
)
from ..model_registry import (
    ModelRegistryError,
    ModelRegistryReader,
    RegistryVersion,
    normalize_model_kind,
    resolve_registry_path,
)
from ..translator import tr


def _qgs_settings_get(key: str) -> Optional[str]:
    """QgsSettings-backed getter for the registry-path override keys.

    Imported lazily so the module still loads where qgis is absent.
    """
    try:
        from qgis.core import QgsSettings

        value = QgsSettings().value(f"EMDS/{key}", "", type=str)
        return str(value) if value else None
    except Exception:
        return None


class ModelRegistryPickerDialog(QDialog):
    """List + select a published model version for a given model kind."""

    def __init__(
        self,
        *,
        model_kind: str,
        registry_path: str = "",
        parent=None,
    ):
        super().__init__(parent)
        self.model_kind = normalize_model_kind(model_kind)
        self.registry_path = registry_path or resolve_registry_path(
            self.model_kind, settings_get=_qgs_settings_get
        )
        self._versions: List[RegistryVersion] = []
        self._selected: Optional[RegistryVersion] = None

        self.setWindowTitle(tr("registry_picker.window_title"))
        self.resize(760, 460)
        self._build()
        self._load_versions()

    # ------------------------------------------------------------------ ui
    def _build(self) -> None:
        layout = QVBoxLayout()
        self.setLayout(layout)

        self.header_label = QLabel(
            tr("registry_picker.header", kind=self.model_kind, path=self.registry_path)
        )
        self.header_label.setWordWrap(True)
        layout.addWidget(self.header_label)

        self.table = QTableWidget(0, 5)
        self.table.setHorizontalHeaderLabels([
            tr("registry_picker.col_name"),
            tr("registry_picker.col_version"),
            tr("registry_picker.col_schema"),
            tr("registry_picker.col_authoring_tool"),
            tr("registry_picker.col_current"),
        ])
        self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
        for col in range(1, 5):
            header.setSectionResizeMode(col, QHeaderView.ResizeMode.ResizeToContents)
        self.table.doubleClicked.connect(self._on_accept)
        self.table.itemSelectionChanged.connect(self._on_selection_changed)
        layout.addWidget(self.table, 1)

        self.status_label = QLabel("")
        self.status_label.setWordWrap(True)
        layout.addWidget(self.status_label)

        button_row = QHBoxLayout()
        self.refresh_button = QPushButton(tr("registry_picker.btn_refresh"))
        self.refresh_button.clicked.connect(self._load_versions)
        button_row.addWidget(self.refresh_button)
        button_row.addStretch()

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

        self._set_ok_enabled(False)

    # -------------------------------------------------------------- loading
    def _load_versions(self) -> None:
        self.table.setRowCount(0)
        self._versions = []
        self.status_label.setText("")
        try:
            reader = ModelRegistryReader(self.registry_path)
            self._versions = reader.list_versions(self.model_kind)
        except ModelRegistryError as exc:
            self.status_label.setText(tr("registry_picker.load_error", error=str(exc)))
            self._set_ok_enabled(False)
            return
        except Exception as exc:  # pragma: no cover - defensive
            self.status_label.setText(tr("registry_picker.load_error", error=str(exc)))
            self._set_ok_enabled(False)
            return

        if not self._versions:
            self.status_label.setText(tr("registry_picker.empty", kind=self.model_kind))
            self._set_ok_enabled(False)
            return

        self.table.setRowCount(len(self._versions))
        for row_idx, version in enumerate(self._versions):
            values = [
                version.model_name or "",
                version.version or "",
                version.schema_version or "",
                version.authoring_tool or "",
                tr("registry_picker.current_marker") if version.is_current else "",
            ]
            for col_idx, value in enumerate(values):
                self.table.setItem(row_idx, col_idx, QTableWidgetItem(str(value)))
        self.status_label.setText(
            tr("registry_picker.count", count=len(self._versions))
        )
        self.table.selectRow(0)

    # ------------------------------------------------------------- actions
    def _on_selection_changed(self) -> None:
        self._set_ok_enabled(self._current_version() is not None)

    def _current_version(self) -> Optional[RegistryVersion]:
        rows = self.table.selectionModel().selectedRows() if self.table.selectionModel() else []
        if not rows:
            return None
        index = rows[0].row()
        if 0 <= index < len(self._versions):
            return self._versions[index]
        return None

    def _on_accept(self) -> None:
        version = self._current_version()
        if version is None:
            QMessageBox.information(
                self,
                tr("registry_picker.window_title"),
                tr("registry_picker.select_required"),
            )
            return
        self._selected = version
        self.accept()

    def _set_ok_enabled(self, enabled: bool) -> None:
        ok_button = self.button_box.button(QDialogButtonBox.StandardButton.Ok)
        if ok_button is not None:
            ok_button.setEnabled(bool(enabled))

    # --------------------------------------------------------------- result
    def selected_version(self) -> Optional[RegistryVersion]:
        return self._selected

    def get_selected_version(self) -> Optional[RegistryVersion]:
        """Exec the dialog modally; return the chosen RegistryVersion or None."""
        if exec_dialog(self) == QDialog.DialogCode.Accepted:
            return self._selected
        return None
