"""Widget for rss item display"""

# standard
from functools import partial
from pathlib import Path

# PyQGIS
from qgis.PyQt import QtCore, uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QImage, QPixmap
from qgis.PyQt.QtWidgets import QWidget

# project
from oslandia.__about__ import DIR_PLUGIN_ROOT
from oslandia.constants import UTM_CONTENT_NEWSFEED
from oslandia.datamodels.mdl_rss_item import RssItem
from oslandia.gui.commons.layout_flow import FlowLayout
from oslandia.gui.commons.wdg_label_context_menu import FilterTagLabel
from oslandia.gui.stylesheet import WidgetStyleSheet
from oslandia.newsfeed.rss_reader import RssReader
from oslandia.toolbelt.cache_manager import CacheManager
from oslandia.toolbelt.file_stats import is_file_older_than
from oslandia.toolbelt.log_handler import PlgLogger
from oslandia.toolbelt.network_manager import NetworkRequestsManager


class RssItemWidget(WidgetStyleSheet):
    """QWidget to display a RSS item in the News feed panel."""

    qsig_newsfeed_filters_changed = QtCore.pyqtSignal(str, str)

    def __init__(self, parent: QWidget | None = None) -> None:
        """Widget instanciation.

        :param parent: dialog parent, defaults to None
        :type parent: Optional[QWidget], optional
        """
        super().__init__(parent)
        ui_path = Path(__file__).resolve(True).parent / "wdg_rss_item.ui"
        uic.loadUi(ui_path, self)
        self.parent = parent
        self.rss_reader = RssReader()
        self.cache_manager = CacheManager(app_prefix=".oslandia", dir_name="cache")
        self.network_manager = NetworkRequestsManager()
        self.log = PlgLogger().log
        self.local_cache_rss_images: Path = self.cache_manager.get_cache_path.joinpath(
            "newsfeed/rss_images/"
        )
        self.flow_layout_item_categories = FlowLayout()
        tagsWidget = QWidget()
        tagsWidget.setLayout(self.flow_layout_item_categories)
        self.item_categories.addWidget(tagsWidget)

    def set_item(self, item: RssItem, nb_cars_allowed: int = 270) -> None:
        """Set rss item displayed.

        :param item: RSS item
        :type item: RssItem
        :param nb_cars_allowed: Nb cars allowed to be displayed, defaults to 270
        :type nb_cars_allowed: int, optional
        """
        if self.rss_reader.is_read(item):
            self.is_read.setStyleSheet("background-color: rgba(0,0,0,0)")

        self.title = item.title
        self.abstract = item.abstract
        self.categories = item.categories
        self.item_date.setText(item.get_date())

        self.update_categories(self.rss_reader.is_read(item))

        self.update_description(nb_cars_allowed)
        self.read_more_button.clicked.connect(partial(self.set_read, item=item))

        # Thumbnail
        cache_days: int = 30
        local_item_thumbnail_filepath: Path | None = None

        if item.image_url:
            local_item_thumbnail_filepath = self.local_cache_rss_images.joinpath(
                item.image_url.rsplit("/", 1)[-1]
            )
            if is_file_older_than(
                local_file_path=local_item_thumbnail_filepath,
                expiration_rotating_hours=cache_days * 24,
                dt_reference_mode="modification",
            ):
                self.network_manager.download_file_to(
                    remote_url=item.image_url,
                    local_path=local_item_thumbnail_filepath,
                    caller=UTM_CONTENT_NEWSFEED,
                )

        # Load when the image is available
        image = QImage()
        if (
            local_item_thumbnail_filepath is None
            or not local_item_thumbnail_filepath.exists()
        ):
            local_item_thumbnail_filepath = DIR_PLUGIN_ROOT.joinpath(
                "resources/images/default_rss_img.png"
            )

        with local_item_thumbnail_filepath.open(mode="rb") as f:
            image.loadFromData(f.read())
            image = image.scaledToWidth(300, Qt.TransformationMode.SmoothTransformation)
            pixmap = QPixmap(image)
            self.item_img.setPixmap(pixmap)

            # GrayScale if the news has been read
            if self.rss_reader.is_read(item):
                self.item_img.setEnabled(False)
                # Change Readmore button caption
                self.read_more_button.setText(self.tr("Read again..."))

        # Button read more onhover
        self.read_more_button.setStyleSheet("""
            QPushButton:hover {
                color: #3a74ac;
            }
        """)

    def update_description(self, nb_cars_allowed: int) -> None:
        """Update rss item description.

        :param item: nb_cars_allowed
        :type item: int
        """
        # Max caracters from title + abstract
        self.item_text.clear()
        nb_cars_left = nb_cars_allowed - len(self.title)
        abstract = self.abstract
        if len(self.abstract) >= nb_cars_left:
            abstract = self.abstract[:nb_cars_left] + "..."

        self.item_text.append(f"<b>{self.title}</b> : {abstract}")
        self.item_text.setFixedHeight(100)

    def update_categories(self, is_read: bool = False) -> None:
        """Update rss item categories

        :param is_read: the item has been read
        :type item: bool
        """
        # Display categories
        if self.flow_layout_item_categories.count() == 0:
            # Creation
            for cat in self.categories:
                if cat is not None and cat != "NewsFR":
                    style = self.get_category_style(is_read, cat)
                    categorie = FilterTagLabel()
                    categorie.qsig_tag_filters_changed.connect(
                        lambda action, tag: self.qsig_newsfeed_filters_changed.emit(
                            action, tag
                        )
                    )
                    categorie.setText(cat)
                    categorie.setStyleSheet(style)
                    self.flow_layout_item_categories.addWidget(categorie)
        else:
            # Update
            for i in range(self.flow_layout_item_categories.count()):
                cat = self.flow_layout_item_categories.itemAt(i).widget()
                cat.setStyleSheet(self.get_category_style(is_read, cat.text()))

    def get_category_style(self, is_read: bool, cat: str) -> str:
        """Return category stylesheet.

        :param is_read: tells if the news has been already read
        :param cat: category to stylise
        """
        bg = "#aaaaaa" if is_read else "#3a74ac"
        color = "#ffffff"
        if self.rss_reader.is_category_in_filters(cat):
            color = "#e9c89e"
        style = "QLabel::hover{background-color : #83b4e2;}"
        style += f"QLabel{{background-color: {bg}; border-radius: 10px; color:{color}; padding: 1px 2px 1px 2px; margin-right:1px;}}"
        return style

    def set_read(self, item: RssItem) -> None:
        """Mark the item as read

        :param guid: ID of the RSS item
        """
        if item:
            self.rss_reader.on_read_item(item)
            self.read_more_button.setText(self.tr("Read again..."))
            self.is_read.setStyleSheet("background-color: rgba(0,0,0,0)")
            self.item_img.setEnabled(False)
            self.update_categories(True)
