#
# Copyright (c) 2021-2026 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from ahriman.core.build_tools.task import Task
from ahriman.core.configuration import Configuration
from ahriman.core.log import LazyLogging
from ahriman.core.utils import full_version, utcnow
from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource
from ahriman.models.pkgbuild import Pkgbuild


class PackageVersion(LazyLogging):
    """
    package version extractor and helper

    Attributes:
        package(Package): package definitions
    """

    def __init__(self, package: Package) -> None:
        """
        Args:
            package(Package): package definitions
        """
        self.package = package

    def actual_version(self, configuration: Configuration) -> str:
        """
        additional method to handle VCS package versions

        Args:
            configuration(Configuration): configuration instance

        Returns:
            str: package version if package is not VCS and current version according to VCS otherwise
        """
        if not self.package.is_vcs:
            return self.package.version

        _, repository_id = configuration.check_loaded()
        paths = configuration.repository_paths
        task = Task(self.package, configuration, repository_id, paths)

        try:
            # create fresh chroot environment, fetch sources and - automagically - update PKGBUILD
            task.init(paths.cache_for(self.package.base), [], None)
            pkgbuild = Pkgbuild.from_file(paths.cache_for(self.package.base) / "PKGBUILD")

            return full_version(pkgbuild.get("epoch"), pkgbuild["pkgver"], pkgbuild["pkgrel"])
        except Exception:
            self.logger.exception("cannot determine version of VCS package %s", self.package.base)
        finally:
            # clear log files generated by devtools
            for log_file in paths.cache_for(self.package.base).glob("*.log"):
                log_file.unlink()

        return self.package.version

    def is_newer_than(self, timestamp: float | int) -> bool:
        """
        check if package was built after the specified timestamp

        Args:
            timestamp(float | int): timestamp to check build date against

        Returns:
            bool: ``True`` in case if package was built after the specified date and ``False`` otherwise.
            In case if build date is not set by any of packages, it returns False
        """
        return any(
            package.build_date > timestamp
            for package in self.package.packages.values()
            if package.build_date is not None
        )

    def is_outdated(self, remote: Package, configuration: Configuration, *,
                    calculate_version: bool = True) -> bool:
        """
        check if package is out-of-dated

        Args:
            remote(Package): package properties from remote source
            configuration(Configuration): configuration instance
            calculate_version(bool, optional): expand version to actual value (by calculating git versions)
                (Default value = True)

        Returns:
            bool: ``True`` if the package is out-of-dated and ``False`` otherwise
        """
        min_allowed_age = configuration.getint("build", "min_age", fallback=0)
        min_build_date = utcnow().timestamp() - min_allowed_age
        if remote.remote.source == PackageSource.AUR and PackageVersion(remote).is_newer_than(min_build_date):
            self.logger.info("package %s was modified too recently, skip update", remote.base)
            return False

        vcs_allowed_age = configuration.getint("build", "vcs_allowed_age", fallback=0)
        min_vcs_build_date = utcnow().timestamp() - vcs_allowed_age
        if calculate_version and not self.is_newer_than(min_vcs_build_date):
            remote_version = PackageVersion(remote).actual_version(configuration)
        else:
            remote_version = remote.version

        return self.package.vercmp(remote_version) < 0
