import json
from dataclasses import dataclass
from functools import lru_cache

# PyQGIS
from qgis.PyQt.QtCore import QUrl

# plugin
from oslandia.constants import UTM_CONTENT_ISSUEBROWSER
from oslandia.gitlab_api.gitlab_object import (
    PageLoadResult,
    get_nb_result_and_page_from_reply,
)
from oslandia.toolbelt import PlgLogger, PlgOptionsManager
from oslandia.toolbelt.network_manager import NetworkRequestsManager


@dataclass
class Labels:
    id: int
    name: str
    description: str
    description_html: str
    text_color: str
    color: str


class LabelsRequestManager:
    MAX_LIMIT = 50

    def get_base_url(self, project_id: int) -> str:
        """
        Get base url for labels of a group

        Args:
            project_id: (int) project id

        Returns: url for labels info

        """
        return f"{self.plg_settings.gitlab_api_url_base}/projects/{project_id}/labels"

    def __init__(self):
        """
        Helper for stored_data request

        """
        self.log = PlgLogger().log
        self.ntwk_requester_blk = NetworkRequestsManager()
        self.plg_settings = PlgOptionsManager.get_plg_settings()

    @lru_cache
    def get_labels_list(self, project_id: int) -> list[Labels]:
        """
        Get list of labels

        Args:
            project_id: (int) project id

        Returns: list of available labels, raise ReadStoredDataException otherwise
        """
        self.log(f"{__name__}.get_labels_list(project:{project_id})")
        result = []
        page_result = self.get_labels_list_by_page(project_id, 1, self.MAX_LIMIT)
        nb_page = page_result.nb_page
        result += page_result.gitlab_object_list
        for page in range(2, nb_page):
            page_result = self.get_labels_list_by_page(project_id, page, self.MAX_LIMIT)
            result += page_result.gitlab_object_list
        return result

    def get_labels_list_by_page(
        self, project_id: int, page: int = 1, limit: int = MAX_LIMIT
    ) -> PageLoadResult:
        """
        Get list of labels

        Args:
            group: (str) group id
            page: (int) page number (start at 1)
            limit: (int)

        Returns: list of available labels
        """

        # send request
        req_reply = self.ntwk_requester_blk.get_url(
            QUrl(
                f"{self.plg_settings.gitlab_api_url_base}projects/{project_id}/labels?page={page}&per_page={limit}"
            ),
            self.plg_settings.authentification_config_id,
            return_req_reply=True,
            caller=UTM_CONTENT_ISSUEBROWSER,
        )
        if req_reply:
            nb_result, nb_page = get_nb_result_and_page_from_reply(req_reply)
            data = json.loads(req_reply.content().data().decode("utf-8"))
            return PageLoadResult(
                nb_object=nb_result,
                nb_page=nb_page,
                page=page,
                gitlab_object_list=[
                    Labels(
                        id=p_data["id"],
                        name=p_data["name"],
                        description=p_data["description"],
                        description_html=p_data["description_html"],
                        text_color=p_data["text_color"],
                        color=p_data["color"],
                    )
                    for p_data in data
                ],
            )
        return PageLoadResult(nb_object=0, nb_page=0, page=0, gitlab_object_list=[])
