"""Background task to download showcase project assets (icons, screenshots)
progressively, without blocking the UI."""

from dataclasses import dataclass
from pathlib import Path

from qgis.core import Qgis, QgsTask
from qgis.PyQt.QtCore import pyqtSignal

from oslandia.constants import UTM_CONTENT_SHOWCASE
from oslandia.toolbelt.log_handler import PlgLogger
from oslandia.toolbelt.network_manager import NetworkRequestsManager


@dataclass(frozen=True)
class ProjectAsset:
    """A single showcase asset (icon or screenshot) to download."""

    project_name: str
    attribute_name: str  # "logo" or "screenshot"
    url: str
    dest_path: Path


class ProjectAssetsDownloadTask(QgsTask):
    """Downloads missing icons/screenshots in the background and emits a
    signal for each asset as it becomes ready, allowing progressive UI updates.
    """

    # project_name, attribute_name ("logo"/"screenshot"), url, local_path
    qsig_asset_ready = pyqtSignal(ProjectAsset)

    def __init__(self, assets: list[ProjectAsset]):
        """Constructor.

        :param assets: assets to download
        :type assets: list[ProjectAsset]
        """
        super().__init__("Oslandia - showcase assets download", QgsTask.Flag.CanCancel)
        self._assets = assets
        self.log = PlgLogger().log

    def run(self) -> bool:
        """Executed on the task's worker thread."""
        network_manager = NetworkRequestsManager()
        total = len(self._assets) or 1

        for i, asset in enumerate(self._assets):
            if self.isCanceled():
                return False

            try:
                network_manager.download_file_to(
                    remote_url=asset.url,
                    local_path=asset.dest_path,
                    caller=UTM_CONTENT_SHOWCASE,
                )
            except Exception as exc:
                self.log(
                    message=f"Download failed for {asset.url}: {exc}",
                    log_level=Qgis.MessageLevel.Warning,
                )
                self.setProgress(int((i + 1) / total * 100))
                continue

            if not asset.dest_path.exists():
                self.log(
                    message=f"Download of {asset.url} completed but file "
                    f"{asset.dest_path} is missing, asset skipped",
                    log_level=Qgis.MessageLevel.Warning,
                )
                self.setProgress(int((i + 1) / total * 100))
                continue

            self.qsig_asset_ready.emit(asset)
            self.setProgress(int((i + 1) / total * 100))

        return True

    def finished(self, result: bool) -> None:
        """Executed on the main thread when the task completes."""
        if not result and not self.isCanceled():
            self.log(
                message="The showcase assets download task failed",
                log_level=Qgis.MessageLevel.Warning,
            )
