"""License manager for ApiPosturePro."""

import hashlib
import json
import os
import socket
from datetime import datetime, timedelta
from pathlib import Path

import httpx
import jwt

from apiposture_pro.licensing.models import LicenseContext, StoredLicense


class ProLicenseManager:
    """Manages Pro license activation, validation, and storage."""

    LICENSE_API_URL = "https://api.apiposture.com/v1/licenses"
    LICENSE_FILE = Path.home() / ".apiposture" / "license.json"
    GRACE_PERIOD_DAYS = 7

    def __init__(self) -> None:
        """Initialize license manager."""
        self.LICENSE_FILE.parent.mkdir(parents=True, exist_ok=True)

    def get_machine_id(self) -> str:
        """Generate unique machine identifier."""
        hostname = socket.gethostname()
        username = os.getenv("USER", os.getenv("USERNAME", "unknown"))
        machine_string = f"{hostname}:{username}"
        return hashlib.sha256(machine_string.encode()).hexdigest()

    def is_valid(self) -> bool:
        """Check if current license is valid."""
        try:
            context = self.get_context()
            return context is not None
        except Exception:
            return False

    def get_context(self) -> LicenseContext | None:
        """Get current license context."""
        stored = self._load_stored_license()
        if not stored:
            # Check environment variable
            env_key = os.getenv("APIPOSTURE_LICENSE_KEY")
            if env_key:
                try:
                    return self._parse_jwt(env_key)
                except Exception:
                    return None
            return None

        # Check if license is expired
        if stored.context:
            if stored.context.expires_at < datetime.utcnow():
                # Check grace period
                grace_cutoff = stored.last_validated_at + timedelta(days=self.GRACE_PERIOD_DAYS)
                if datetime.utcnow() > grace_cutoff:
                    return None

        return stored.context

    def activate(self, license_key: str) -> LicenseContext:
        """
        Activate a license key.

        Args:
            license_key: License key to activate

        Returns:
            LicenseContext with license information

        Raises:
            Exception: If activation fails
        """
        machine_id = self.get_machine_id()

        # Parse JWT to validate format
        context = self._parse_jwt(license_key)
        context.machine_id = machine_id

        # Call activation API (mock for now)
        try:
            with httpx.Client(timeout=10.0) as client:
                response = client.post(
                    f"{self.LICENSE_API_URL}/activate",
                    json={"license_key": license_key, "machine_id": machine_id},
                )
                response.raise_for_status()
        except httpx.HTTPError:
            # For development, allow activation even if API is unreachable
            pass

        # Store license
        stored = StoredLicense(
            license_key=license_key,
            activated_at=datetime.utcnow(),
            last_validated_at=datetime.utcnow(),
            machine_id=machine_id,
            context=context,
        )
        self._save_stored_license(stored)

        return context

    def deactivate(self) -> None:
        """Deactivate current license."""
        if self.LICENSE_FILE.exists():
            self.LICENSE_FILE.unlink()

    def _parse_jwt(self, license_key: str) -> LicenseContext:
        """Parse JWT token to extract license information."""
        try:
            # Decode without verification for development
            # In production, use proper JWT verification with public key
            payload = jwt.decode(license_key, options={"verify_signature": False})

            return LicenseContext(
                license_key=license_key,
                tier=payload.get("tier", "pro"),
                features=payload.get("features", []),
                expires_at=datetime.fromtimestamp(payload.get("exp", 0)),
                customer_name=payload.get("customer_name", ""),
                customer_email=payload.get("customer_email", ""),
            )
        except Exception as e:
            raise ValueError(f"Invalid license key format: {e}") from e

    def _load_stored_license(self) -> StoredLicense | None:
        """Load stored license from disk."""
        if not self.LICENSE_FILE.exists():
            return None

        try:
            with open(self.LICENSE_FILE) as f:
                data = json.load(f)

            context = None
            if data.get("context"):
                ctx_data = data["context"]
                context = LicenseContext(
                    license_key=ctx_data["license_key"],
                    tier=ctx_data["tier"],
                    features=ctx_data["features"],
                    expires_at=datetime.fromisoformat(ctx_data["expires_at"]),
                    customer_name=ctx_data["customer_name"],
                    customer_email=ctx_data["customer_email"],
                    machine_id=ctx_data.get("machine_id"),
                )

            return StoredLicense(
                license_key=data["license_key"],
                activated_at=datetime.fromisoformat(data["activated_at"]),
                last_validated_at=datetime.fromisoformat(data["last_validated_at"]),
                machine_id=data["machine_id"],
                context=context,
            )
        except Exception:
            return None

    def _save_stored_license(self, stored: StoredLicense) -> None:
        """Save license to disk."""
        data = {
            "license_key": stored.license_key,
            "activated_at": stored.activated_at.isoformat(),
            "last_validated_at": stored.last_validated_at.isoformat(),
            "machine_id": stored.machine_id,
            "context": None,
        }

        if stored.context:
            data["context"] = {
                "license_key": stored.context.license_key,
                "tier": stored.context.tier,
                "features": stored.context.features,
                "expires_at": stored.context.expires_at.isoformat(),
                "customer_name": stored.context.customer_name,
                "customer_email": stored.context.customer_email,
                "machine_id": stored.context.machine_id,
            }

        with open(self.LICENSE_FILE, "w") as f:
            json.dump(data, f, indent=2)
