"""
Cryptographic Item Hyperlinking and Snapshot Authentication Service.
Generates and validates HMAC-SHA256 signatures to prevent spoofing items in chat.
Stores snapshots with 24h TTL to eliminate database queries when players view tooltips.
"""

from __future__ import annotations

import hashlib
import hmac
import time
from typing import Dict, Optional, Tuple

from server.chat.chat_types import ItemAffixDTO, ItemSnapshotDTO, QueryItemSnapshotResponseDTO


class ItemLinkService:
    """
    Manages authentic item linking for chat flexing.
    Enforces HMAC-SHA256 validation to ensure 100% item integrity.
    """

    DEFAULT_TTL_SECONDS = 86400  # 24 hours snapshot retention

    def __init__(self, secret_signing_key: bytes = b"FREEEXILE_SECRET_SIGNING_KEY_2026") -> None:
        self.secret_key = secret_signing_key
        # In-memory snapshot cache: item_uuid -> (ItemSnapshotDTO, expiry_timestamp)
        self._snapshot_cache: Dict[str, Tuple[ItemSnapshotDTO, float]] = {}

    def compute_signature(
        self,
        item_uuid: str,
        item_name_key: str,
        rarity: int,
        element: Optional[int] = None,
        quality: Optional[int] = None,
        item_level: Optional[int] = None,
    ) -> str:
        """
        Computes server-authoritative HMAC-SHA256 signature for an item.
        Default signature covers (item_uuid, item_name_key, rarity).
        If full attributes are provided, computes signature over full specs.
        """
        if element is not None and quality is not None and item_level is not None:
            message = f"{item_uuid}:{item_name_key}:{rarity}:{element}:{quality}:{item_level}".encode("utf-8")
        else:
            message = f"{item_uuid}:{item_name_key}:{rarity}".encode("utf-8")
        return hmac.new(self.secret_key, message, hashlib.sha256).hexdigest()

    def create_item_snapshot(
        self,
        item_uuid: str,
        item_name_key: str,
        rarity: int,
        element: int,
        quality: int,
        item_level: int,
        crafter_name: str,
        affixes: Tuple[ItemAffixDTO, ...] = (),
        created_at_ms: Optional[int] = None,
        ttl_seconds: int = DEFAULT_TTL_SECONDS,
    ) -> ItemSnapshotDTO:
        """
        Generates an authenticated item snapshot and caches it for chat broadcast.
        Guarantees 24h TTL cache to protect inventory databases.
        """
        signature = self.compute_signature(item_uuid, item_name_key, rarity)
        now_ms = created_at_ms if created_at_ms is not None else int(time.time() * 1000)

        snapshot = ItemSnapshotDTO(
            item_uuid=item_uuid,
            item_name_key=item_name_key,
            rarity=rarity,
            element=element,
            quality=quality,
            item_level=item_level,
            crafter_name=crafter_name,
            hmac_signature=signature,
            created_at_ms=now_ms,
            affixes=affixes,
        )

        expiry = time.time() + ttl_seconds
        self._snapshot_cache[item_uuid] = (snapshot, expiry)
        return snapshot

    def verify_item_signature(
        self,
        item_uuid: str,
        item_name_key: str,
        rarity: int,
        claimed_signature: str,
        element: Optional[int] = None,
        quality: Optional[int] = None,
        item_level: Optional[int] = None,
    ) -> bool:
        """
        Verifies if the claimed signature matches the item's immutable attributes.
        Uses constant-time comparison to prevent timing attacks.
        """
        expected_basic = self.compute_signature(item_uuid, item_name_key, rarity)
        if hmac.compare_digest(expected_basic, claimed_signature):
            return True
        if element is not None and quality is not None and item_level is not None:
            expected_full = self.compute_signature(item_uuid, item_name_key, rarity, element, quality, item_level)
            if hmac.compare_digest(expected_full, claimed_signature):
                return True
        return False

    def query_item_snapshot(self, item_uuid: str, claimed_signature: str) -> QueryItemSnapshotResponseDTO:
        """
        Queries an item snapshot for tooltip rendering.
        Validates both signature integrity and cache TTL.
        """
        self._cleanup_expired()

        entry = self._snapshot_cache.get(item_uuid)
        if not entry:
            return QueryItemSnapshotResponseDTO(
                is_valid=False,
                error_message="Item snapshot not found or has expired."
            )

        snapshot, expiry = entry
        if time.time() > expiry:
            del self._snapshot_cache[item_uuid]
            return QueryItemSnapshotResponseDTO(
                is_valid=False,
                error_message="Item snapshot has expired."
            )

        if not hmac.compare_digest(snapshot.hmac_signature, claimed_signature):
            return QueryItemSnapshotResponseDTO(
                is_valid=False,
                error_message="Cryptographic signature mismatch! Potential item spoofing attempt."
            )

        return QueryItemSnapshotResponseDTO(
            is_valid=True,
            item_snapshot=snapshot
        )

    def _cleanup_expired(self) -> None:
        """Purges expired snapshots from memory cache."""
        now = time.time()
        expired_keys = [k for k, (_, exp) in self._snapshot_cache.items() if now > exp]
        for k in expired_keys:
            del self._snapshot_cache[k]
