# standard
from pathlib import Path

# qgis
from qgis.core import QgsApplication
from qgis.PyQt import uic
from qgis.PyQt.QtCore import QSize, Qt
from qgis.PyQt.QtGui import QColor, QIcon, QPixmap
from qgis.PyQt.QtWidgets import QGridLayout, QTableWidgetItem, QWidget

# project
from oslandia.__about__ import DIR_PLUGIN_ROOT
from oslandia.datamodels.mdl_projects_browser import ProjectObj, ProjectsObj
from oslandia.gui.showcase.wdg_cards_project import ProjectCardsWidget
from oslandia.gui.stylesheet import DialogStyleSheet
from oslandia.showcase.showcase_manager import ShowcaseManager
from oslandia.toolbelt import PlgLogger
from oslandia.toolbelt.cache_manager import CacheManager
from oslandia.toolbelt.preferences import PlgOptionsManager


class Showcase(DialogStyleSheet):
    def __init__(self, parent: QWidget | None = None) -> None:
        # init module and ui
        super().__init__(parent)
        uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self)
        self.log = PlgLogger().log
        self.plugin_manager = ShowcaseManager()
        # icon
        self.setWindowIcon(
            QIcon(str(DIR_PLUGIN_ROOT.joinpath("resources/images/plugin.png")))
        )

        # cache
        self.cache_manager = CacheManager(".oslandia", "cache")

        # Data
        self.qgis_projects_obj = ProjectsObj(self.cache_manager.get_cache_path)
        self.plugins = self.qgis_projects_obj.get_projects("plugin")
        self.qgis = self.qgis_projects_obj.get_projects("qgis")
        self.others = self.qgis_projects_obj.get_projects("other")

        self.table_projects.itemSelectionChanged.connect(self.display_informations)
        self.table_projects.setIconSize(QSize(25, 25))
        self.populate_table()
        self.change_stack_buttons()

        if not PlgOptionsManager.get_plg_settings().debug_mode:
            self.lbl_date_refresh_json.setVisible(False)
            self.tb_refresh_json.setVisible(False)
        else:
            self.lbl_date_refresh_json.setText(
                "Information last updated: "
                + self.plugin_manager.get_date_json_projects_update
            )

            # Action buttons
            self.tb_refresh_json.clicked.connect(self.force_update_json)

            # Icon buttons
            self.tb_refresh_json.setIcon(
                QIcon(QgsApplication.iconPath("mActionRefresh.svg"))
            )

        # make the dialog a window to allow resizing
        self.setWindowFlags(Qt.WindowType.Window)

        # Label style
        self.label_plugins.setStyleSheet("font-weight: bold; font-size: 25px;")
        self.label_qgis.setStyleSheet("font-weight: bold; font-size: 25px;")
        self.label_other.setStyleSheet("font-weight: bold; font-size: 25px;")

        # Cards
        self.add_cards_to_grid(self.grid, self.plugins)
        self.add_cards_to_grid(self.grid2, self.qgis)
        self.add_cards_to_grid(self.grid3, self.others)

        # Apply the last view
        self.stack.setCurrentIndex(
            PlgOptionsManager.get_plg_settings().project_browser_last_view
        )

    def add_cards_to_grid(self, grid: QGridLayout, projects: list[ProjectObj]) -> None:
        """Add a list of projects to the table_projects.

        :param projects: List of ProjectObj to add.
        :param source: Source of the projects, used for the 'WhatsThis' field.
        """

        columns = 3
        for index, project in enumerate(projects):
            row = index // columns
            col = index % columns
            self.log(message=f"Displaying card for project: {project.name}")
            widget = ProjectCardsWidget(self, project.about)
            widget.set_display_data(project)
            grid.addWidget(widget, row, col)

    def change_stack_buttons(self) -> None:
        """Adds icons and actions to the buttons used to change pages in the stack."""
        buttons = [
            (self.tb_view_list, "view_list.svg", 1),
            (self.tb_view_cards, "view_cards.svg", 0),
        ]

        for button, icon_name, index in buttons:
            button.setIcon(
                QIcon(str(DIR_PLUGIN_ROOT / f"resources/images/{icon_name}"))
            )

            button.clicked.connect(lambda _, i=index: self.stack.setCurrentIndex(i))
            button.clicked.connect(
                lambda _, i=index: PlgOptionsManager().set_value_from_key(
                    key="project_browser_last_view", value=int(i)
                )
            )

    def force_update_json(self) -> None:
        """Download last json from gitlab pages"""
        self.plugin_manager.force_update_json_projects()
        self.lbl_date_refresh_json.setText(
            self.tr("Information last updated: ")
            + self.plugin_manager.get_date_json_projects_update
        )
        self.populate_table()

    def populate_table(self) -> None:
        """Populate the table_projects with public, gitlab, and private projects."""
        self.clear_table()
        self.add_projects_to_table(self.plugins, "plugin")
        self.add_projects_to_table(self.qgis, "qgis")
        self.add_projects_to_table(self.others, "other")

        self.table_projects.setSortingEnabled(True)

    def add_projects_to_table(self, projects: list[ProjectObj], source: str) -> None:
        """Add a list of projects to the table_projects.

        :param projects: List of ProjectObj to add.
        :param source: Source of the projects, used for the 'WhatsThis' field.
        """
        for project in projects:
            row_position = self.table_projects.rowCount()
            self.table_projects.insertRow(row_position)

            # Création de l'item pour le nom du project
            item = QTableWidgetItem(project.name)
            item.setData(Qt.ItemDataRole.UserRole, project)
            project_logo = project.logo
            project_icon_pixmap = None

            if project_logo:
                icon = self.plugin_manager.get_project_icon(project.name, project_logo)
                if icon:
                    # Set constant size for icons
                    project_icon_pixmap = icon.pixmap(icon.actualSize(QSize(100, 100)))

            if not project_icon_pixmap:
                # Empty icon if no icon
                project_icon_pixmap = QPixmap(100, 100)
                project_icon_pixmap.fill(QColor(255, 255, 255, 0))

            item.setIcon(QIcon(project_icon_pixmap.scaled(QSize(100, 100))))

            item.setWhatsThis(source)
            self.table_projects.setItem(row_position, 0, item)

        self.table_projects.sortItems(0, order=Qt.SortOrder.AscendingOrder)
        # Select first item
        self.table_projects.selectRow(0)

    def clear_table(self):
        """remove all line on table_projects"""
        self.table_projects.setRowCount(0)

    def display_informations(self) -> None:
        """Displays the detailed information of the selected item and configures the UI
        elements accordingly.

        Updates text fields and buttons based on the selected item's details,
        including name, version, description, and various URLs.

        :return: None
        """
        oslandia_project = self.get_selected_projet()
        if oslandia_project is not None:
            self.wdg_showcase_project.set_display_data(oslandia_project)

    def get_selected_projet(self) -> ProjectObj | None:
        """Retrieves the ProjectObj object based on the selection."""
        selected_items = self.table_projects.selectedItems()
        if selected_items:
            item = selected_items[0]
            project = item.data(Qt.ItemDataRole.UserRole)
            return project

        return None
