"""Result of offline token validation."""

from __future__ import annotations

import time
from dataclasses import dataclass
from typing import Any


@dataclass(frozen=True)
class OfflineValidationResult:
    """Result of offline token validation.

    Use the class methods ``invalid()``, ``expired()``, and ``from_payload()``
    to construct instances.
    """

    valid: bool
    status: str
    error_code: str | None
    license_id: str | None
    entitlements: dict[str, Any] | None
    expires_at: str | None
    activation_limit: int | None
    activation_count: int
    identifier: str | None
    activated: bool
    issued_at: int
    expires_at_timestamp: int
    ttl: int
    uses_count: int
    max_uses: int | None

    @classmethod
    def invalid(cls, error_code: str) -> OfflineValidationResult:
        """Create a result for an invalid token (format, signature, etc.)."""
        return cls(
            valid=False,
            status="unknown",
            error_code=error_code,
            license_id=None,
            entitlements=None,
            expires_at=None,
            activation_limit=None,
            activation_count=0,
            identifier=None,
            activated=False,
            issued_at=0,
            expires_at_timestamp=0,
            ttl=0,
            uses_count=0,
            max_uses=None,
        )

    @classmethod
    def expired(cls, payload: dict[str, Any]) -> OfflineValidationResult:
        """Create a result for an expired token (signature was valid but token has expired)."""
        return cls.from_payload(payload, valid=False, error_code="TOKEN_EXPIRED")

    @classmethod
    def from_payload(
        cls,
        payload: dict[str, Any],
        valid: bool,
        error_code: str | None = None,
    ) -> OfflineValidationResult:
        """Create a result from a decoded token payload."""
        return cls(
            valid=valid,
            status=payload.get("status", "unknown"),
            error_code=error_code,
            license_id=payload.get("license_id"),
            entitlements=payload.get("entitlements"),
            expires_at=payload.get("expires_at"),
            activation_limit=payload.get("activation_limit"),
            activation_count=payload.get("activation_count", 0),
            identifier=payload.get("identifier"),
            activated=payload.get("activated", False),
            issued_at=payload.get("iat", 0),
            expires_at_timestamp=payload.get("exp", 0),
            ttl=payload.get("ttl", 0),
            uses_count=payload.get("uses_count", 0),
            max_uses=payload.get("max_uses"),
        )

    def is_valid(self) -> bool:
        """Whether the offline token is valid (signature OK and not expired)."""
        return self.valid

    def is_expired(self) -> bool:
        """Whether the offline token has expired."""
        return self.expires_at_timestamp < int(time.time())

    def remaining_seconds(self) -> int:
        """Get the number of seconds remaining before the token expires."""
        return max(0, self.expires_at_timestamp - int(time.time()))

    def to_dict(self) -> dict[str, Any]:
        """Serialize to a plain dictionary."""
        return {
            "valid": self.valid,
            "status": self.status,
            "error_code": self.error_code,
            "license_id": self.license_id,
            "entitlements": self.entitlements,
            "expires_at": self.expires_at,
            "activation_limit": self.activation_limit,
            "activation_count": self.activation_count,
            "identifier": self.identifier,
            "activated": self.activated,
            "issued_at": self.issued_at,
            "expires_at_timestamp": self.expires_at_timestamp,
            "ttl": self.ttl,
            "uses_count": self.uses_count,
            "max_uses": self.max_uses,
        }
