"""Customize display of issue table view"""

# standard

# PyQGIS
from typing import Any

from qgis.PyQt.QtCore import (
    QAbstractItemModel,
    QDateTime,
    QEvent,
    QLocale,
    QModelIndex,
    QSize,
    Qt,
)
from qgis.PyQt.QtGui import QColor, QFontMetrics, QPainter
from qgis.PyQt.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem, QTableView

# project
from oslandia.constants import UTM_CONTENT_ISSUEBROWSER
from oslandia.gui.helpdesk.mdl_issue import IssuesListModel
from oslandia.toolbelt.network_manager import open_url_in_browser
from oslandia.toolbelt.qt_utils import localize_qdatetime


class IssueTableViewDelegate(QStyledItemDelegate):
    def __init__(self, parent_tab_view: QTableView | None = None) -> None:
        """Initialize the delegate for the issue table view.

        :param parent_tab_view: The parent table view, defaults to None
        :type parent_tab_view: QTableView | None, optional
        """
        super().__init__(parent_tab_view)

        # We need that to receive mouse move events in editorEvent
        parent_tab_view.setMouseTracking(True)

        # Revert the mouse cursor when the mouse isn't over
        # an item but still on the view widget
        parent_tab_view.viewportEntered.connect(parent_tab_view.unsetCursor)

    def displayText(self, value: Any, locale: QLocale) -> str:  # noqa: N802
        """Display text for a value.
        Used to localize datetime

        :param value: value to display
        :type value: Any
        :param locale: locale to use
        :type locale: QLocale
        :return: display text for value
        :rtype: str
        """
        if isinstance(value, QDateTime):
            return localize_qdatetime(value)
        else:
            return super().displayText(value, locale)

    def paint(
        self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex
    ):
        """Paint current index

        :param painter: painter
        :type painter: QPainter
        :param option: option
        :type option: QStyleOptionViewItem
        :param index: index to paint
        :type index: QModelIndex
        """

        if index.column() == IssuesListModel.STATE_COL:
            # Customizing the background for the "bubble"
            painter.save()

            # Get the text from the index
            text = index.data()

            if text != "opened":
                # Fill the background with the selected color
                painter.setBrush(QColor("whitesmoke"))
                painter.setPen(Qt.PenStyle.NoPen)
                painter.drawRect(option.rect)

            # Calculate the size of the text
            font_metrics = QFontMetrics(option.font)
            text_rect = font_metrics.boundingRect(text)
            text_rect.adjust(0, 0, 10, 0)  # Add some padding for the bubble

            # Calculate the position to center the bubble inside the cell
            bubble_rect = text_rect
            bubble_rect.moveCenter(option.rect.center())

            # Set the bubble color (background)
            if text == "opened":
                bubble_color = QColor("lightgreen")
            else:
                bubble_color = QColor("lightgrey")

            painter.setBrush(bubble_color)
            painter.setPen(Qt.PenStyle.NoPen)

            # Draw a rounded rectangle around the text (bubble)
            painter.drawRoundedRect(bubble_rect, 10, 10)

            # Draw the text inside the bubble
            painter.setPen(Qt.GlobalColor.black)
            painter.drawText(bubble_rect, Qt.AlignmentFlag.AlignCenter, text)

            # Restore the painter state
            painter.restore()
        elif index.column() == IssuesListModel.WEB_URL_COL:
            painter.save()

            # Récupérer le texte de l'index
            text = index.data()

            # Configurer le style pour ressembler à un lien (texte bleu et souligné)
            font = option.font
            font.setUnderline(True)
            painter.setFont(font)
            painter.setPen(QColor(0, 0, 255))  # Bleu pour le lien

            # Dessiner le texte comme un lien
            painter.drawText(
                option.rect,
                Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter,
                text,
            )
            # Restore the painter state
            painter.restore()
        else:
            super().paint(painter, option, index)

    def editorEvent(  # noqa: N802
        self,
        event: QEvent,
        model: QAbstractItemModel,
        option: QStyleOptionViewItem,
        index: QModelIndex,
    ) -> bool:
        """Override editorEvent to open link for web URL.

        :param event: editor event
        :type event: QEvent
        :param model: current mode
        :type model: QAbstractItemModel
        :param option: options
        :type option: QStyleOptionViewItem
        :param index: model index
        :type index: QModelIndex

        :return: True if the event was handled, False otherwise
        :rtype: bool
        """
        if (
            index.column() == IssuesListModel.WEB_URL_COL
            and event.type() == QEvent.Type.MouseButtonRelease
        ):
            if event.button() == Qt.MouseButton.LeftButton:
                url = index.data(Qt.ItemDataRole.UserRole)
                open_url_in_browser(url, UTM_CONTENT_ISSUEBROWSER)
                return True
        if event.type() == QEvent.Type.MouseMove:
            if index.column() == IssuesListModel.WEB_URL_COL:
                self.parent().setCursor(Qt.CursorShape.PointingHandCursor)
            else:
                self.parent().unsetCursor()

        return super().editorEvent(event, model, option, index)

    def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize:  # noqa: N802
        """Returns the size needed by the delegate to display the item specified by index,
        taking into account the style information provided by option.

        :param option: option
        :type option: QStyleOptionViewItem
        :param index: index to paint
        :type index: QModelIndex

        :return: size hint
        :rtype: QSize
        """
        if index.column() == IssuesListModel.STATE_COL:
            # Adjust the size hint to account for the text and the bubble
            text = index.data()
            font_metrics = QFontMetrics(option.font)
            text_size = font_metrics.size(Qt.TextFlag.TextSingleLine, text)
            return text_size + QSize(20, 10)  # Add padding around the text
        return super().sizeHint(option, index)
