#  Copyright 2026 European Union
#  Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
#  SPDX-License-Identifier: EUPL-1.2
"""Dialog for selecting processors to add to the pipeline.

:Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
:Description: Display available processors in a list and return the selected names.
"""

from __future__ import annotations

from PySide6.QtCore import QSortFilterProxyModel, QStringListModel, Qt
from PySide6.QtGui import QFontMetrics
from PySide6.QtWidgets import (
    QDialog,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListView,
    QPushButton,
    QVBoxLayout,
    QWidget,
)


class AddProcessorDialog(QDialog):
    """Dialog presenting a selectable list of processors."""

    def __init__(self, processors: list[str], parent: QWidget | None = None) -> None:
        super().__init__(parent)
        self.setWindowTitle('Add Processor')
        self._model = QStringListModel(processors)

        self._proxy_model = QSortFilterProxyModel(self)
        self._proxy_model.setSourceModel(self._model)
        self._proxy_model.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)

        self.list_view = QListView()
        self.list_view.setModel(self._proxy_model)
        self.list_view.setSelectionMode(QListView.SelectionMode.ExtendedSelection)

        self.filter_edit = QLineEdit()
        self.filter_edit.setClearButtonEnabled(True)
        self.filter_edit.setPlaceholderText('Filter processors...')

        self._processors = processors
        self._prompt = QLabel('Select one or more processors to append to the pipeline')
        self._prompt.setWordWrap(True)

        self.add_button = QPushButton('Add')
        self.add_button.setEnabled(False)
        self.cancel_button = QPushButton('Cancel')

        self._setup_layout()
        self._wire_signals()
        self._adjust_width()

    def selected_names(self) -> list[str]:
        """Return the currently selected processor names."""

        indexes = self.list_view.selectionModel().selectedIndexes()
        return [idx.data() for idx in indexes]

    def _setup_layout(self) -> None:
        buttons = QHBoxLayout()
        buttons.addStretch(1)
        buttons.addWidget(self.cancel_button)
        buttons.addWidget(self.add_button)

        layout = QVBoxLayout()
        layout.addWidget(self._prompt)
        layout.addWidget(self.filter_edit)
        layout.addWidget(self.list_view)
        layout.addLayout(buttons)
        self.setLayout(layout)

    def _adjust_width(self) -> None:
        metrics = QFontMetrics(self.list_view.font())
        longest = 0
        for name in self._processors:
            longest = max(longest, metrics.horizontalAdvance(name))
        padding = metrics.horizontalAdvance('W') * 4
        minimum = longest + padding
        minimum = max(minimum, self._prompt.sizeHint().width())
        minimum = max(minimum, self.filter_edit.sizeHint().width())
        if minimum < 200:
            minimum = 200
        self.list_view.setMinimumWidth(minimum)
        self.setMinimumWidth(minimum + 80)

    def _wire_signals(self) -> None:
        self.list_view.selectionModel().selectionChanged.connect(self._update_add_enabled)
        self.list_view.doubleClicked.connect(lambda *_: self.accept())
        self.add_button.clicked.connect(self.accept)
        self.cancel_button.clicked.connect(self.reject)
        self.filter_edit.textChanged.connect(self._proxy_model.setFilterFixedString)

    def _update_add_enabled(self, *_: object) -> None:
        has_selection = bool(self.list_view.selectionModel().selectedIndexes())
        self.add_button.setEnabled(has_selection)
