from qgis.PyQt.QtWidgets import (
    QComboBox,
    QGridLayout,
    QMessageBox,
    QRadioButton,
    QWidget,
    QWizardPage,
)

from openlog.datamodel.assay.generic_assay import AssayDefinition
from openlog.datamodel.connection.openlog_connection import OpenLogConnection
from openlog.gui.import_assay.assay_definition_widget import AssayDefinitionWidget


class AssaySelectionPageWizard(QWizardPage):
    def __init__(self, parent: QWidget, openlog_connection: OpenLogConnection) -> None:
        """
        QWizard to define assay

        Args:
            openlog_connection: OpenLogConnection
            parent : QWidget parent
        """
        super().__init__(parent)

        self._openlog_connection = openlog_connection
        self.setTitle("Downhole data selection")

        assay_definitions = (
            openlog_connection.get_assay_iface().get_all_available_assay_definitions()
        )

        layout = QGridLayout()

        # Radiobutton for assay selection or assay creation
        self.assay_selection_rb = QRadioButton("Available downhole data")
        layout.addWidget(self.assay_selection_rb, 0, 0)

        self.assay_creation_rb = QRadioButton("Create downhole data")
        layout.addWidget(self.assay_creation_rb, 1, 0)

        # Combobox for assay selection
        self.assay_selection_combo = QComboBox(self)
        # Initialization with available assay definition
        for assay_def in assay_definitions:
            self.assay_selection_combo.addItem(
                assay_def.display_name, assay_def
            )  # AssayDefinition stored in combo
        layout.addWidget(self.assay_selection_combo, 0, 1)

        # Widget to display assay definition
        self.assay_definition_widget = AssayDefinitionWidget(self)
        layout.addWidget(self.assay_definition_widget, 2, 0, 1, 2)

        # Connect change for assay definition display
        self.assay_selection_combo.currentTextChanged.connect(
            self._assay_selection_changed
        )
        self.assay_selection_rb.toggled.connect(self._assay_selection_changed)
        self.assay_creation_rb.toggled.connect(self._assay_selection_changed)

        # No assay selection if no assay available
        self.assay_selection_rb.setEnabled(len(assay_definitions) != 0)

        # Default selection
        self.assay_selection_rb.setChecked(len(assay_definitions) != 0)
        self.assay_creation_rb.setChecked(len(assay_definitions) == 0)

        self.setLayout(layout)

    def validatePage(self) -> bool:
        """
        Validate page by checking that a valid assay variable is used

        Returns: True if a valid assay variable is used, False otherwise

        """
        valid = True
        if self.assay_creation_needed():
            available_assay = [
                self.assay_selection_combo.itemText(i)
                for i in range(self.assay_selection_combo.count())
            ]
            variable = (
                self.assay_definition_widget.get_assay_definition_without_columns().variable
            )
            if not variable:
                valid = False
                QMessageBox.warning(
                    self,
                    "Invalid downhole data variable",
                    f"Downhole data variable not defined.",
                )

            if variable in available_assay:
                valid = False
                QMessageBox.warning(
                    self,
                    "Invalid downhole data variable",
                    f"Downhole data variable '{variable}' already used.",
                )

        return valid

    def assay_creation_needed(self) -> bool:
        """
        Check if assay creation is needed

        Returns: True if assay creation is needed, False otherwise

        """
        return self.assay_creation_rb.isChecked()

    def get_assay_definition(self) -> AssayDefinition:
        """
        Returns AssayDefinition from widget

        Returns: AssayDefinition

        """
        if self.assay_creation_needed():
            return self.assay_definition_widget.get_assay_definition_without_columns()
        else:
            return self.assay_selection_combo.currentData()

    def _assay_selection_changed(self) -> None:
        """
        Update definition widget when selection updated or creation asked

        """
        self.assay_definition_widget.setEnabled(self.assay_creation_rb.isChecked())
        if self.assay_selection_rb.isChecked():
            self.assay_definition_widget.set_assay_definition(
                self.assay_selection_combo.currentData()
            )

    def reinitialize_available_assays(self) -> None:
        """
        Refresh selection QCombobox with available assays.
        """
        assay_definitions = (
            self._openlog_connection.get_assay_iface().get_all_available_assay_definitions()
        )
        self.assay_selection_combo.currentTextChanged.disconnect(
            self._assay_selection_changed
        )
        for assay_def in assay_definitions:
            self.assay_selection_combo.addItem(assay_def.display_name, assay_def)

        self.assay_selection_combo.currentTextChanged.connect(
            self._assay_selection_changed
        )
