from __future__ import annotations

"""Licence manager responsible for loading, validating and providing subscription information."""

import json
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Dict, Optional

from .crypto_utils import (
    LicenceCryptoError,
    decrypt_payload,
    derive_aes_key,
    verify_signature,
)


@dataclass
class LicenceInfo:
    licence_id: str
    tier: str
    max_users: int
    max_domains: int
    valid_until: datetime
    features: Dict[str, bool]
    super_admin_email: str
    db_seed: str
    hardware_fingerprint: Optional[str]
    grace_period_hours: int
    last_validation: Optional[datetime]


class LicenceError(Exception):
    """Raised when licence cannot be loaded/validated."""


class LicenceManager:
    """High-level API for licence handling."""

    def __init__(self, licence_path: Path):
        self.licence_path = licence_path
        self.current_licence: Optional[LicenceInfo] = None

    def load(self, hardware_fingerprint: str = "") -> LicenceInfo:
        if not self.licence_path.exists():
            raise LicenceError("Licence file missing.")

        payload = json.loads(self.licence_path.read_text(encoding="utf-8"))
        signature = payload.pop("signature", "")
        if not signature:
            raise LicenceError("Licence signature missing.")

        verify_signature(payload, signature)

        encryption_info = payload.get("encryption", {})
        seed = encryption_info.get("seed")
        if not seed:
            raise LicenceError("Encryption seed missing in licence.")

        try:
            key = derive_aes_key(seed, hardware_fingerprint)
            decrypted = decrypt_payload(
                key, encryption_info["nonce"], encryption_info["ciphertext"], encryption_info["tag"]
            )
        except LicenceCryptoError as exc:
            raise LicenceError(str(exc)) from exc

        config = json.loads(decrypted.decode("utf-8"))
        subscription = config["subscription"]

        features = {feature: True for feature in subscription.get("features", [])}

        licence = LicenceInfo(
            licence_id=config.get("licenseId", "UNKNOWN"),
            tier=subscription.get("tier", "FREE"),
            max_users=subscription.get("maxUsers", 1),
            max_domains=subscription.get("maxDomains", 1),
            valid_until=datetime.fromisoformat(subscription.get("validUntil").replace("Z", "+00:00")),
            features=features,
            super_admin_email=config.get("superAdmin", {}).get("email", ""),
            db_seed=config.get("encryption", {}).get("dbKeySeed", ""),
            hardware_fingerprint=config.get("antiTampering", {}).get("hardwareFingerprint"),
            grace_period_hours=config.get("validation", {}).get("gracePeriodHours", 168),
            last_validation=None,
        )

        if licence.valid_until < datetime.now(timezone.utc):
            raise LicenceError("Licence expired.")

        self.current_licence = licence
        return licence
