"""Dialog for issue creation"""

# standard
from functools import partial
from pathlib import Path

# PyQGIS
from qgis.core import Qgis
from qgis.gui import QgsMessageBar
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QDialogButtonBox, QVBoxLayout, QWidget
from qgis.utils import OverrideCursor

# project
from oslandia.__about__ import __icon_path__
from oslandia.constants import UTM_CONTENT_ISSUEBROWSER
from oslandia.gui.helpdesk.mdl_project import ProjectListModel
from oslandia.gui.helpdesk.mdl_project_manager import ProjectListModelManager
from oslandia.gui.helpdesk.proxy_model_project import ProjectProxyModel
from oslandia.gui.helpdesk.wdg_issue import IssueWidget
from oslandia.gui.stylesheet import DialogStyleSheet
from oslandia.helpdesk.issue import IssuesRestRequestManager
from oslandia.helpdesk.project import ProjectRequestManager
from oslandia.toolbelt import PlgLogger
from oslandia.toolbelt.network_manager import open_url_in_browser
from oslandia.toolbelt.preferences import PlgOptionsManager
from oslandia.toolbelt.qgis_info import (
    get_active_plugin_info,
    get_installed_qgis_info_as_markdown,
)


class CreateIssueDialog(DialogStyleSheet):
    """QDialog to create a new issue in a selected project."""

    def __init__(self, group_id: int, parent: QWidget | None = None) -> None:
        """Initialize helpdesk and projects issues browser.

        :param group_id: gitlab group id for project selection
        :type group_id: int
        :param parent: dialog parent, defaults to None
        :type parent: QWidget | None, optional
        """
        super().__init__(parent)
        uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self)

        # Customize dialog window
        self.setWindowTitle(self.tr("Create issue"))
        self.setWindowIcon(QIcon(str(__icon_path__)))
        self.setWindowFlags(Qt.WindowType.Window)
        self.setSizeGripEnabled(True)

        # modules as attributes
        self.plg_settings = PlgOptionsManager.get_plg_settings()
        self.project_request = ProjectRequestManager()

        with OverrideCursor(Qt.CursorShape.WaitCursor):
            self.mdl_project = ProjectListModelManager.get_model_for_group(group_id)

        # Proxy model to filter archived projects and sort by name
        self.proxy_mdl = ProjectProxyModel(self)
        self.proxy_mdl.setSourceModel(self.mdl_project)
        self.proxy_mdl.show_archived(False)  # Can't create issue in archived project

        # Set current project  with last value used if defined in settings
        if self.plg_settings.issue_creation_last_project_id:
            self.set_current_project_id(
                self.plg_settings.issue_creation_last_project_id
            )
        self.wdg_issue_context_auth.load_settings()
        self.wdg_issue.set_display_mode(IssueWidget.DisplayMode.CREATE)
        self.proxy_mdl.setSortCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
        self.proxy_mdl.sort(ProjectListModel.NAME_COL, Qt.SortOrder.AscendingOrder)

        # projects selection combobox
        self.cbx_projects.setModel(self.proxy_mdl)
        self.cbx_projects.setModelColumn(ProjectListModel.NAME_COL)

        # if user has access to a single project only
        if self.proxy_mdl.rowCount() == 1:
            self.cbx_projects.hide()
        elif self.proxy_mdl.rowCount() > 1:
            self.cbx_projects.show()
            self.cbx_projects.setEnabled(True)
            # signal
            self.cbx_projects.currentIndexChanged.connect(self._project_changed)
        else:
            self.log("No projects available.")

        # button box
        self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setDefault(True)
        self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setText(
            self.tr("Submit")
        )
        self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False)
        self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setToolTip(
            self.tr("Issue not valid.\nPlease fill mandatory parameters.")
        )

        # signals
        self.wdg_issue.qsig_issue_changed.connect(self._issue_changed)
        self.btn_box.button(QDialogButtonBox.StandardButton.Ok).clicked.connect(
            self.on_btn_submit
        )

        # QMessageBar
        self.message_bar = QgsMessageBar()
        layout = self.findChild(QVBoxLayout, "message_layout")
        layout.insertWidget(0, self.message_bar)

        # Simulate project changes for project_id definition in widgets
        self._project_changed()

    def set_current_project_id(self, project_id: int) -> None:
        """Define current selected project

        :param project_id: project id
        :type project_id: int
        """
        with OverrideCursor(Qt.CursorShape.WaitCursor):
            self.mdl_project.wait_for_data_load()

            project_row = self.mdl_project.get_project_row(project_id)
            if project_row != -1:
                index = self.proxy_mdl.mapFromSource(
                    self.mdl_project.index(project_row, self.mdl_project.NAME_COL)
                )
                self.cbx_projects.setCurrentIndex(index.row())

    def _issue_changed(self) -> None:
        """Update submit button if issue is valid for creation"""
        with OverrideCursor(Qt.CursorShape.WaitCursor):
            if not self.wdg_issue.get_issue().valid_for_creation():
                self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setEnabled(
                    False
                )
                self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setToolTip(
                    self.tr("Issue not valid.\nPlease fill mandatory parameters.")
                )
            else:
                self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setEnabled(True)
                self.btn_box.button(QDialogButtonBox.StandardButton.Ok).setToolTip("")

    def _project_changed(self) -> None:
        """Update issue widget for current project"""
        with OverrideCursor(Qt.CursorShape.WaitCursor):
            self.wdg_issue.set_current_project_id(self.selected_project_id())
            current_project_mdl_idx = self.proxy_mdl.mapFromSource(
                self.mdl_project.index(
                    self.mdl_project.get_project_row(self.selected_project_id()),
                    ProjectListModel.NAME_COL,
                )
            )
            self.setWindowTitle(
                self.tr("Create issue")
                + " - "
                + self.proxy_mdl.data(
                    current_project_mdl_idx,
                    role=Qt.ItemDataRole.DisplayRole,
                )
            )
            self.setWindowIcon(
                self.proxy_mdl.data(
                    current_project_mdl_idx,
                    role=Qt.ItemDataRole.DecorationRole,
                )
            )

    def selected_project_id(self) -> int:
        """Get selected project id

        :return: selected project id
        :rtype: int
        """
        project_index = self.cbx_projects.currentIndex()
        return self.mdl_project.data(
            self.proxy_mdl.mapToSource(
                self.proxy_mdl.index(project_index, ProjectListModel.ID)
            )
        )

    def on_btn_submit(self) -> None:
        """Create issue"""
        self.wdg_issue_context_auth.save_settings()

        issue = self.wdg_issue.get_issue()

        description = issue.description

        if self.wdg_issue_context_auth.is_send_qgis_info_enabled():
            description += f"\n### {self.tr('QGIS Information')}\n"
            description += get_installed_qgis_info_as_markdown()
            description += "\n"

        if self.wdg_issue_context_auth.is_send_plugin_info_enabled():
            description += f"\n### {self.tr('Installed plugins informations')}\n"
            active_plugin_info = get_active_plugin_info()
            for plugin_name, version in active_plugin_info.items():
                description += f"\n * {plugin_name} : {version}"
                description += "\n"

        issue.description = description

        issue_manager = IssuesRestRequestManager()
        create_issue = issue_manager.create_issue(self.selected_project_id(), issue)

        self.wdg_issue.clear_issue()

        PlgLogger().log(
            message=f'Issue <b>"{create_issue.name}</b>" successfully created.',
            log_level=Qgis.MessageLevel.Success,
            push=True,
            duration=10,
            button=True,
            button_text=self.tr("Open on Gitlab..."),
            button_connect=partial(
                open_url_in_browser,
                create_issue.web_url,
                UTM_CONTENT_ISSUEBROWSER,
            ),
            parent_location=self,
            nb_parent_max_for_message_bar=0,
        )
