#! python3  # noqa: E265

"""Onboarding dialog logic."""

# standard
from enum import Enum
from pathlib import Path
from typing import Optional

# PyQGIS
from qgis.core import Qgis
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QCloseEvent, QIcon, QPixmap
from qgis.PyQt.QtWidgets import QMessageBox, QWidget

# Plugin
from oslandia.__about__ import DIR_PLUGIN_ROOT
from oslandia.gui.onboarding.wdg_authentification_page import AuthenticationPage
from oslandia.gui.onboarding.wdg_customer_page import CustomerPage
from oslandia.gui.onboarding.wdg_features_create_issue import CreateIssueFeaturesPage
from oslandia.gui.onboarding.wdg_features_helpdesk_customer import HelpdeskFeaturesPage
from oslandia.gui.onboarding.wdg_logged_in_success_page import LoggedInfoPage
from oslandia.gui.onboarding.wdg_news_feed_features_page import NewsFeedFeaturesPage
from oslandia.gui.onboarding.wdg_showcase_features_page import ShowcaseFeaturesPage
from oslandia.gui.onboarding.wdg_welcome_page import WelcomePage
from oslandia.gui.stylesheet import DialogStyleSheet
from oslandia.toolbelt.log_handler import PlgLogger
from oslandia.toolbelt.preferences import PlgOptionsManager


class CloseChoice(Enum):
    SKIP = "skip"
    REMIND = "remind"


class OnboardingDialog(DialogStyleSheet):
    """On-boarding dialog."""

    def __init__(self, parent: Optional[QWidget] = None) -> None:
        """Dialog to define current connection as authentication config.

        :param parent: parent widget, defaults to None
        :type parent: QObject, optional
        """
        # Initialize module and UI
        super().__init__(parent)
        uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self)
        # Logger
        self.logger = PlgLogger()

        # Is customer or not
        self.is_customer: bool | None = None

        self.initGui()

    def initGui(self) -> None:  # noqa: N802
        """Set up UI elements."""

        self.setWindowTitle(self.tr("Get started!"))
        pixmap = QPixmap(
            str(DIR_PLUGIN_ROOT / "resources/images/oslandia_logo_sans_texte.svg")
        )
        self.setWindowIcon(QIcon(pixmap))

        self.lb_logo.setPixmap(
            pixmap.scaled(
                pixmap.width(),
                100,
                Qt.AspectRatioMode.KeepAspectRatio,
                Qt.TransformationMode.SmoothTransformation,
            )
        )

        self.setModal(True)

        # Connect buttons
        self.btn_remind_later.clicked.connect(self.on_remind_later)
        self.btn_skip.clicked.connect(self.on_skip)

        # Icons
        self.icon_skip = QIcon(str(DIR_PLUGIN_ROOT / "resources/images/skip.svg"))
        self.icon_later = QIcon(str(DIR_PLUGIN_ROOT / "resources/images/later.svg"))
        self.btn_skip.setIcon(self.icon_skip)
        self.btn_remind_later.setIcon(self.icon_later)

        # Custom stacked widget
        welcome_page = WelcomePage()
        self.custom_stacked_wdg.add_page(welcome_page)  # Index 0
        # When user click on start onboarding, buttons are not visible
        welcome_page.start_signal.connect(self.disable_buttons)

        customer_page = CustomerPage()
        customer_page.is_customer_signal.connect(self._on_customer_status_changed)
        self.custom_stacked_wdg.add_page(customer_page)  # Index 1

        # Authentication page - accessible only if customer
        authentification_page = AuthenticationPage()
        self.custom_stacked_wdg.add_page(
            authentification_page, can_access=lambda: self.is_customer is True
        )  # Index 2

        # Logged info page - accessible only if customer
        log_info_page = LoggedInfoPage()
        self.custom_stacked_wdg.add_page(
            log_info_page, can_access=lambda: self.is_customer is True
        )  # Index 3

        # Features page for customers - accessible only if customer
        wdg_features_helpdesk_customer = HelpdeskFeaturesPage()
        self.custom_stacked_wdg.add_page(
            wdg_features_helpdesk_customer, can_access=lambda: self.is_customer is True
        )  # Index 4

        wdg_features_create_issue_customer = CreateIssueFeaturesPage()
        self.custom_stacked_wdg.add_page(
            wdg_features_create_issue_customer,
            can_access=lambda: self.is_customer is True,
        )  # Index 5

        # Showcase features page
        showcase_features_page = ShowcaseFeaturesPage()
        self.custom_stacked_wdg.add_page(showcase_features_page)  # Index 6

        # News feed features page
        news_feed_features_page = NewsFeedFeaturesPage()
        self.custom_stacked_wdg.add_page(news_feed_features_page)  # Index 7
        news_feed_features_page.end_signal.connect(self.on_end_onboarding)

        # Start on the welcome page
        self.custom_stacked_wdg.set_current_page(0)

    def disable_buttons(self) -> None:
        """Disable Remind me later and skip buttons"""
        self.btn_skip.setVisible(False)
        self.btn_remind_later.setVisible(False)

    def on_remind_later(self) -> None:
        """Handle Remind Me Later button click: close dialog without disabling future
        prompts."""
        self.logger.log(
            message=self.tr(
                "You have chosen not to onboard the plugin at this time. "
                "You will be reminded to do so the next time you launch the application."
            ),
            log_level=Qgis.MessageLevel.Info,
            duration=10,
            push=True,
        )
        self.accept()

    def on_skip(self) -> None:
        """Handle Skip button click: close dialog and disable future onboarding prompts."""
        PlgOptionsManager().set_value_from_key(key="run_onboarding", value=False)
        self.logger.log(
            message=self.tr(
                "You have chosen to skip the plugin onboarding process. It will no "
                "longer be offered to you unless you select it in the settings."
            ),
            log_level=Qgis.MessageLevel.Info,
            duration=10,
            push=True,
        )
        self.accept()

    def on_end_onboarding(self) -> None:
        """Handle the end of the onboarding process."""
        PlgOptionsManager().set_value_from_key(key="run_onboarding", value=False)
        self.logger.log(
            message=self.tr(
                "Onboarding process is complete. It will no longer be offered to you "
                "unless you select it in the settings."
            ),
            log_level=Qgis.MessageLevel.Info,
            push=False,
        )
        self.accept()

    def closeEvent(self, event: QCloseEvent) -> None:  # noqa: N802
        """Handle window close event."""
        choice: CloseChoice = self._show_close_confirmation()

        if choice == CloseChoice.SKIP:
            self.on_skip()
        else:  # REMIND or None (dialog closed)
            self.on_remind_later()

        event.accept()

    def _show_close_confirmation(self) -> CloseChoice:
        """Show confirmation dialog when closing.

        :return: CloseChoice.SKIP or CloseChoice.REMIND based on user choice
        :rtype: CloseChoice
        """
        msg_box = QMessageBox(self)
        msg_box.setWindowTitle(self.tr("Close onboarding?"))
        msg_box.setText(self.tr("What would you like to do?"))
        msg_box.setIcon(QMessageBox.Icon.Question)

        skip_button = msg_box.addButton(
            self.tr("Skip"), QMessageBox.ButtonRole.RejectRole
        )
        skip_button.setIcon(self.icon_skip)
        remind_button = msg_box.addButton(
            self.tr("Remind me later"), QMessageBox.ButtonRole.AcceptRole
        )
        remind_button.setIcon(self.icon_later)
        msg_box.setDefaultButton(remind_button)

        msg_box.exec()
        clicked_button = msg_box.clickedButton()

        if clicked_button == skip_button:
            return CloseChoice.SKIP
        else:
            return CloseChoice.REMIND

    def _on_customer_status_changed(self, is_customer: bool) -> None:
        """Handle customer status change.

        :param is_customer: True if user is a customer, False otherwise
        :type is_customer: bool
        """
        self.is_customer: bool = is_customer

        # Refresh page accessibility
        self.custom_stacked_wdg.refresh_accessibility()
