import asyncio
import logging
from pathlib import Path
import os

from gateway_core.application.ports.DownloadPort import DownloadPort
from gateway_core.application.ports.FileSystemPort import FileSystemPort
from gateway_core.application.ports.NotificationPort import NotificationPort
from gateway_core.domain.FileSystemData import FileUpgradeDto

logger = logging.getLogger(__name__)

class FileUpgradeUseCase:
    def __init__(
            self,
            fileSystem: FileSystemPort,
            downloadAdapter: DownloadPort,
            notifier: NotificationPort,
    ) -> None:
        self._fileSystem = fileSystem
        self._downloadAdapter = downloadAdapter
        self._notifier = notifier

    async def execute(self, fileUpgradDto: FileUpgradeDto) -> bool:
        """
        This function upgrades a conifg file.

        A file is downloaded form the given URL.
        Checked with the given checksum.

        :param fileUpgradeDto: FileUpgradeDto
        """
        # download file (and notify every 10s)
        ECP_WORKING_DIR = os.environ.get("ECP_WORK_FILES_DIR", "")
        configDownloadPath = fileUpgradDto.destinationPath

        logger.info(f"configDownloadPath: {configDownloadPath}")
        with self._fileSystem.getFile(configDownloadPath, True) as downloadedConfigFile:
            [isDownloadSuccess, _] = await asyncio.gather(*[self._downloadAdapter.downloadFile(downloadedConfigFile, fileUpgradDto.downloadUrl),
                                                       self._notifier.notifyConfigFileDownload(fileUpgradDto.taskId, self._downloadAdapter.getCurrentDownloadStatus)])

        self._downloadAdapter.resetDownloadStatus()

        if not isDownloadSuccess:
            self._fileSystem.deleteFile(configDownloadPath)
            return False

        # notify installing
        await self._notifier.notifyUpgradeProgress(fileUpgradDto.taskId, "Installing", 0)

        # generate and check checksum
        checksum = self._fileSystem.getChecksum(configDownloadPath, fileUpgradDto.checksumType)

        if checksum != fileUpgradDto.checksum:
            logger.error(f"Checksum does not match! Calculated: {checksum}, given: {fileUpgradDto.checksum}")
            await self._notifier.notifyUpgradeProgress(fileUpgradDto.taskId, "InstallationFailed", 0)
            self._fileSystem.deleteFile(configDownloadPath)
            return False

        await self._notifier.notifyUpgradeProgress(fileUpgradDto.taskId, "Installed", 100)

        return True