"""Cache service for managing boost status caching."""

from typing import Final

from diskcache import Cache
from loguru import logger as log

from fedibooster.protocols import BoostableProtocol

CACHE_MAX_AGE_DEFAULT_30_DAYS: Final[int] = 30


class CacheService:
    """Service for managing cache operations related to boosting."""

    def __init__(self, cache: Cache, default_expiry: int = CACHE_MAX_AGE_DEFAULT_30_DAYS * 86400):
        """Initialize the cache service.

        Args:
            cache: The diskcache Cache instance
            default_expiry: Default expiration time in seconds (default: 30 days)

        """
        self.cache = cache
        self.default_expiry = default_expiry

    def has_been_boosted(self, status_id: str | None, status_url: str | None, ap_id: str | None) -> bool:
        """Check if a status has already been boosted.

        Args:
            status_id: The status ID
            status_url: The status URL
            ap_id: The ActivityPub ID

        Returns:
            True if the status has already been boosted, False otherwise

        """
        if status_id and self.cache.get(key=status_id, default=False):
            log.debug(f"Status {status_id} has already been boosted. SKIPPING")
            return True

        if status_url and self.cache.get(key=status_url, default=False):
            log.debug(f"Status URL {status_url} has already been boosted. SKIPPING")
            return True

        if ap_id and self.cache.get(key=ap_id, default=False):
            log.debug(f"Status ap_id {ap_id} has already been boosted. SKIPPING")
            return True

        return False

    def record_boost(self, boostable: BoostableProtocol) -> None:
        """Record that a status has been boosted.

        Args:
            boostable: An object implementing the BoostableProtocol

        """
        self._cache_set(boostable.status_id)
        if boostable.status_url:
            self._cache_set(boostable.status_url)
        if boostable.status_apid:
            self._cache_set(boostable.status_apid)

        for attachment_hash in boostable.attachments_hashes:
            self._cache_set(attachment_hash)

    def _cache_set(self, key: str | None) -> None:
        """Set a cache key with consistent expiration.

        Args:
            key: The cache key to set

        """
        if key:
            self.cache.set(key, True, expire=self.default_expiry)

    def get_attachment_cache_status(self, attachment_hash: str) -> bool:
        """Check if an attachment hash is already in the cache.

        Args:
            attachment_hash: The hash of the attachment

        Returns:
            True if the attachment is already cached, False otherwise

        """
        return bool(self.cache.get(key=attachment_hash, default=False))

    def record_attachment(self, attachment_hash: str) -> None:
        """Record an attachment hash in the cache.

        Args:
            attachment_hash: The hash of the attachment to record

        """
        self._cache_set(attachment_hash)

    def get_max_boosted_id(self) -> str | None:
        """Get the maximum boosted ID from cache.

        Returns:
            The maximum boosted ID or None if not found

        """
        return self.cache.get(key="max-boosted-id")

    def set_max_boosted_id(self, max_id: str) -> None:
        """Set the maximum boosted ID in cache.

        Args:
            max_id: The maximum boosted ID to set

        """
        self.cache.set(key="max-boosted-id", value=max_id)
