from abc import abstractmethod
from typing import Any

from qgis.core import QgsTask
from qgis.PyQt.QtCore import QObject, Qt

from oslandia.gui.helpdesk.mdl_gitlab_object import AbstractGitlabObjectModel
from oslandia.helpdesk.gitlab_object import PageLoadResult
from oslandia.helpdesk.labels import Labels, LabelsRequestManager


class LabelsListModel(AbstractGitlabObjectModel):
    NAME_COL = 0
    DESCRIPTION_COL = 1

    def __init__(self, parent: QObject = None):
        """
        QStandardItemModel for datastore list display

        Args:
            parent: QObject parent
        """
        super().__init__(parent)
        self.allows_null_value = True

    @abstractmethod
    def _column_headers(self) -> list[str]:
        """Returns headers list"""
        return [
            self.tr("Name"),
        ]

    @abstractmethod
    def _object_data_for_role(
        self,
        gitlab_object: Any,
        col: int,
        role: Qt.ItemDataRole = Qt.ItemDataRole.DisplayRole,
    ) -> Any:
        """Return qt model data for a specific column and role

        :param gitlab_object: object to display
        :type gitlab_object: Any
        :param col: column for table display
        :type col: int
        :param role: qt role, defaults to Qt.ItemDataRole.DisplayRole
        :type role: ItemDataRole., optional

        :return: qt model data
        :rtype: Any
        """
        label: Labels = gitlab_object

        if role == Qt.ItemDataRole.DisplayRole:
            res = {
                self.NAME_COL: label.name,
                self.DESCRIPTION_COL: label.description,
            }
            return res.get(col, None)
        if role == Qt.ItemDataRole.UserRole:
            res = {self.NAME_COL: label}
            return res.get(col, None)

        return None

    def _load_task_description(self) -> str:
        """Test display in QGIS task manager for page load task

        :return: page load description
        :rtype: str
        """
        return self.tr("Load labels for project {}").format(self.obj_filter)

    @abstractmethod
    def _load_object_page(
        self, task: QgsTask | None, obj_filter: Any, page: int
    ) -> PageLoadResult | None:
        """Load labels list for a project for a specific page

        :param task: task used for load, can be None
        :type task: QgsTask, optional
        :param obj_filter: filter reprensenting project id. Must be a str
        :type obj_filter: Any
        :param page: page to load
        :type page: int
        :return: page load result, None in case of error
        :rtype: Optional[PageLoadResult]
        """
        try:
            manager = LabelsRequestManager()
            return manager.get_labels_list_by_page(
                obj_filter, page=page, limit=self.nb_item_by_page
            )
        except ConnectionError:
            return None
