"""Tests for license validation endpoints and CLI activation."""

from __future__ import annotations

import json
from datetime import UTC, datetime, timedelta
from typing import TYPE_CHECKING
from unittest.mock import AsyncMock, patch

if TYPE_CHECKING:
    from pathlib import Path

import pytest

_has_fastapi = pytest.importorskip("fastapi", reason="fastapi not installed")


# ---------------------------------------------------------------------------
# License validation (POST /v1/license/validate)
# ---------------------------------------------------------------------------


class TestLicenseValidateEndpoint:
    """Tests for the /v1/license/validate route logic."""

    async def test_valid_key_returns_tier(self) -> None:
        from backend.api.routes.license import validate_license

        now = datetime.now(UTC)
        expiry = (now + timedelta(days=365)).isoformat()

        mock_key_doc = {
            "customer_id": "ctm_123",
            "tier": "pro",
            "status": "active",
            "expires_at": expiry,
            "features": ["html_report", "ai_explain"],
        }

        with (
            patch(
                "backend.shared.firestore.get_license_key",
                new_callable=AsyncMock,
                return_value=mock_key_doc,
            ),
            patch(
                "backend.shared.firestore.get_customer_by_email",
                new_callable=AsyncMock,
                return_value={"email": "u@e.com"},
            ),
            patch(
                "backend.api.routes.license._generate_signed_url",
                return_value="https://signed.url",
            ),
        ):
            from backend.api.routes.license import ValidateRequest

            resp = await validate_license(ValidateRequest(key_hash="abc123"))
            body = json.loads(resp.body)
            assert resp.status_code == 200
            assert body["tier"] == "pro"
            assert "profile_url" in body

    async def test_invalid_key_returns_401(self) -> None:
        from backend.api.routes.license import ValidateRequest, validate_license

        with patch(
            "backend.shared.firestore.get_license_key",
            new_callable=AsyncMock,
            return_value=None,
        ):
            resp = await validate_license(ValidateRequest(key_hash="bad"))
            assert resp.status_code == 401
            body = json.loads(resp.body)
            assert body["error"] == "invalid_key"

    async def test_revoked_key_returns_401(self) -> None:
        from backend.api.routes.license import ValidateRequest, validate_license

        mock_doc = {"status": "revoked", "expires_at": "", "customer_id": "ctm_1"}
        with patch(
            "backend.shared.firestore.get_license_key",
            new_callable=AsyncMock,
            return_value=mock_doc,
        ):
            resp = await validate_license(ValidateRequest(key_hash="abc"))
            assert resp.status_code == 401
            body = json.loads(resp.body)
            assert body["error"] == "revoked"

    async def test_expired_key_returns_401(self) -> None:
        from backend.api.routes.license import ValidateRequest, validate_license

        expired = (datetime.now(UTC) - timedelta(days=1)).isoformat()
        mock_doc = {"status": "active", "expires_at": expired, "customer_id": "ctm_1"}
        with patch(
            "backend.shared.firestore.get_license_key",
            new_callable=AsyncMock,
            return_value=mock_doc,
        ):
            resp = await validate_license(ValidateRequest(key_hash="abc"))
            assert resp.status_code == 401
            body = json.loads(resp.body)
            assert body["error"] == "expired"


# ---------------------------------------------------------------------------
# CLI activation
# ---------------------------------------------------------------------------


class TestCLIActivation:
    def test_cache_written_on_success(self, tmp_path: Path) -> None:
        """Verify cache file is created after successful activation."""
        from complyform.core.auth.license import LicenseCache, LicenseManager

        mgr = LicenseManager(config_dir=tmp_path)
        now_iso = datetime.now(UTC).isoformat()
        cache = LicenseCache(
            cache_version=1,
            key_hash="abc123",
            tier="pro",
            assess_frameworks=["all"],
            remediate_frameworks=["soc2"],
            features=["html_report"],
            project_limit=1,
            expires_at=(datetime.now(UTC) + timedelta(days=365)).isoformat(),
            last_validated_at=now_iso,
        )
        mgr.save_cache(cache)

        loaded = mgr.load_cache()
        assert loaded is not None
        assert loaded.tier == "pro"
        assert loaded.key_hash == "abc123"

    def test_invalid_key_format_raises(self) -> None:
        from complyform.core.auth.license import LicenseManager
        from complyform.core.errors import LicenseInvalidError

        mgr = LicenseManager()
        with pytest.raises(LicenseInvalidError):
            mgr.activate_online("bad_key_format")


# ---------------------------------------------------------------------------
# Auto-refresh
# ---------------------------------------------------------------------------


class TestAutoRefresh:
    def test_fresh_cache_no_refresh(self, tmp_path: Path) -> None:
        """Cache < 1hr old should not trigger refresh."""
        from complyform.core.auth.license import LicenseCache, LicenseManager

        mgr = LicenseManager(config_dir=tmp_path)
        cache = LicenseCache(
            cache_version=1,
            key_hash="abc123",
            tier="pro",
            assess_frameworks=["all"],
            remediate_frameworks=[],
            features=[],
            project_limit=1,
            expires_at=None,
            last_validated_at=datetime.now(UTC).isoformat(),
        )
        mgr.save_cache(cache)

        assert mgr.is_cache_fresh(cache) is True
        assert mgr.should_auto_refresh(cache) is False

    def test_stale_cache_triggers_refresh(self, tmp_path: Path) -> None:
        """Cache > 1hr old should trigger refresh."""
        from complyform.core.auth.license import LicenseCache, LicenseManager

        mgr = LicenseManager(config_dir=tmp_path)
        stale_time = (datetime.now(UTC) - timedelta(hours=2)).isoformat()
        cache = LicenseCache(
            cache_version=1,
            key_hash="abc123",
            tier="pro",
            assess_frameworks=["all"],
            remediate_frameworks=[],
            features=[],
            project_limit=1,
            expires_at=None,
            last_validated_at=stale_time,
        )
        mgr.save_cache(cache)

        assert mgr.is_cache_fresh(cache) is False
        assert mgr.should_auto_refresh(cache) is True
