from enum import IntFlag

from qgis.PyQt.QtWidgets import (
    QGridLayout,
    QLabel,
    QMessageBox,
    QSizePolicy,
    QWidget,
    QWizard,
    QWizardPage,
)

from openlog.datamodel.connection.interfaces.write_interface import WriteInterface
from openlog.datamodel.connection.openlog_connection import OpenLogConnection
from openlog.gui.import_data.wizard.collar import CollarsImportPageWizard
from openlog.gui.import_data.wizard.dataset import DatasetSelectionPageWizard
from openlog.gui.import_data.wizard.person import PersonSelectionPageWizard
from openlog.gui.import_data.wizard.survey import SurveysImportPageWizard
from openlog.toolbelt import PlgTranslator


class ConfirmationPageWizard(QWizardPage):
    def __init__(
        self,
        parent: QWidget,
        openlog_connection: OpenLogConnection,
        import_wizard_pages: [QWizardPage],
    ) -> None:
        """
        QWizardPage used to confirm data imports and commit database session

        Args:
            openlog_connection: OpenLogConnection used to import data
            import_wizard_pages: List of QWizardPage defining data to be imported
        """
        super().__init__(parent)
        self._openlog_connection = openlog_connection
        self._import_wizard_pages = import_wizard_pages

        self.setTitle(self.tr("Import summary"))

        label = QLabel(
            self.tr("Here are the data that will be imported in your connection.")
        )
        label.setWordWrap(True)

        self.layout = QGridLayout()
        self.layout.addWidget(label, 0, 0, 1, 2)
        self.setLayout(self.layout)

    def initializePage(self) -> None:
        """
        Initialize page before show.

        Create a the list of imported data in the widget.

        """
        self._clean_layout()
        for import_wizard_page in self._import_wizard_pages:
            row = self.layout.rowCount()
            name_edit = QLabel(import_wizard_page.data_label())
            name_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
            self.layout.addWidget(name_edit, row + 1, 0)
            val_edit = QLabel(str(import_wizard_page.data_count()))
            font = val_edit.font()
            font.setBold(True)
            val_edit.setFont(font)
            self.layout.addWidget(val_edit, row + 1, 1)

    def _clean_layout(self) -> None:
        while self.layout.count() > 1:
            layout_item = self.layout.takeAt(1)
            if layout_item.widget():
                layout_item.widget().deleteLater()

    def validatePage(self) -> bool:
        """
        Import data

        Returns: True if no import error occured, False otherwise

        """
        valid = True
        try:
            for import_wizard_page in self._import_wizard_pages:
                import_wizard_page.import_data()
            self._openlog_connection.commit()
        except (
            OpenLogConnection.ImportException,
            WriteInterface.ImportException,
        ) as exc:
            valid = False
            QMessageBox.warning(self, self.tr("Import exception"), str(exc))
            self._openlog_connection.rollback()
        return valid


class ImportPages(IntFlag):
    """
    Define flags for import pages
    For example ImportPages.COLLAR | ImportPages.SURVEY | ImportPages.LITH for Collar, Survey and Lithology import
    https://docs.python.org/fr/3/library/enum.html#intflag
    """

    COLLAR = 1
    SURVEY = 2


class DatabaseImportWizard(QWizard):
    def rejected(self) -> None:
        """
        Rollback openlog connection if data import is rejected

        """
        self.openlog_connection.rollback()
        super(DatabaseImportWizard).rejected()

    def __init__(
        self,
        openlog_connection: OpenLogConnection,
        parent: QWidget = None,
        import_pages=ImportPages.COLLAR | ImportPages.SURVEY,
    ) -> None:
        """
        QWizard to import data into xplordb database from .csv files.

        Args:
            openlog_connection: OpenLogConnection used to import data
            parent : QWidget parent
            import_pages: ImportPages flags to define which data can be imported for example ImportPages.COLLAR | ImportPages.SURVEY | ImportPages.LITH
        """
        super().__init__(parent)
        self.openlog_connection = openlog_connection

        # translation
        self.tr = PlgTranslator().tr
        self.setWindowTitle(self.tr("Data import"))

        # List of wizard used to import data (data will be imported with list order)
        self.data_import_wizards = [
            PersonSelectionPageWizard(self, self.openlog_connection),
            DatasetSelectionPageWizard(self, self.openlog_connection),
        ]

        if ImportPages.COLLAR in import_pages:
            self.data_import_wizards.append(
                CollarsImportPageWizard(self, self.openlog_connection)
            )

        if ImportPages.SURVEY in import_pages:
            self.data_import_wizards.append(
                SurveysImportPageWizard(self, self.openlog_connection)
            )

        for data_import_wizard in self.data_import_wizards:
            self.addPage(data_import_wizard)

        self.confirmation_page = ConfirmationPageWizard(
            self, self.openlog_connection, self.data_import_wizards
        )

        # Wizard to confirm data import and commit database connection
        self.addPage(self.confirmation_page)
