"""Tests for the full activation flow (activate CLI command)."""

import json
import pytest
from datetime import datetime, timedelta
from pathlib import Path
from unittest.mock import patch, MagicMock

from click.testing import CliRunner

from stablestack.cli import main


@pytest.fixture
def runner():
    return CliRunner()


@pytest.fixture(autouse=True)
def reset_caches():
    """Reset all caches between tests."""
    from stablestack.licensing import invalidate_license_cache
    from stablestack.checkers.loader import invalidate_cache
    invalidate_license_cache()
    invalidate_cache()
    yield
    invalidate_license_cache()
    invalidate_cache()


class TestActivateCommand:
    @patch("stablestack.licensing.validate_license_server")
    @patch("stablestack.licensing.save_license_cache")
    @patch("stablestack.licensing.invalidate_license_cache")
    def test_successful_activation_no_bundle(
        self, mock_invalidate, mock_save, mock_validate, runner
    ):
        mock_validate.return_value = {
            "valid": True,
            "customer_name": "Alice",
            "license_type": "individual",
            "expires_at": (datetime.now() + timedelta(days=365)).isoformat(),
            "max_projects": 3,
            "download_url": "",  # No bundle available
        }
        result = runner.invoke(main, ["activate", "sk_live_test123"])
        assert result.exit_code == 0
        assert "License valid" in result.output
        assert "individual" in result.output
        mock_save.assert_called_once()

    @patch("stablestack.licensing.validate_license_server")
    def test_invalid_key_shows_error(self, mock_validate, runner):
        from stablestack.licensing import LicenseError
        mock_validate.side_effect = LicenseError("Invalid license key")
        result = runner.invoke(main, ["activate", "sk_live_bad"])
        assert result.exit_code == 1
        assert "failed" in result.output.lower()

    @patch("stablestack.checkers.downloader.download_checker_bundle")
    @patch("stablestack.checkers.loader.load_paid_checkers")
    @patch("stablestack.licensing.validate_license_server")
    @patch("stablestack.licensing.save_license_cache")
    @patch("stablestack.licensing.invalidate_license_cache")
    def test_activation_with_bundle_download(
        self,
        mock_invalidate,
        mock_save,
        mock_validate,
        mock_load_paid,
        mock_download,
        runner,
        tmp_path,
    ):
        mock_validate.return_value = {
            "valid": True,
            "customer_name": "Bob",
            "license_type": "team",
            "expires_at": (datetime.now() + timedelta(days=365)).isoformat(),
            "max_projects": 10,
            "download_url": "https://example.com/bundle.tar.gz",
        }
        mock_download.return_value = tmp_path / "checkers"
        mock_load_paid.return_value = [MagicMock()] * 65  # 65 paid checkers

        result = runner.invoke(main, ["activate", "sk_live_team123"])
        assert result.exit_code == 0
        assert "License valid" in result.output
        assert "team" in result.output
        assert "65" in result.output
        mock_download.assert_called_once()


class TestStatusCommand:
    @patch("stablestack.licensing.get_cached_license")
    def test_status_free_tier(self, mock_license, runner):
        mock_license.return_value = (False, None, "No license key found")
        result = runner.invoke(main, ["status"])
        assert result.exit_code == 0
        assert "Free tier" in result.output
        assert "stablestack activate" in result.output

    @patch("stablestack.licensing.get_cached_license")
    def test_status_licensed(self, mock_license, runner):
        from stablestack.licensing import LicenseInfo
        info = LicenseInfo(
            customer_name="Alice",
            customer_email="alice@test.com",
            license_type="enterprise",
            expires_at=datetime.now() + timedelta(days=365),
            max_projects=0,
        )
        mock_license.return_value = (True, info, None)
        result = runner.invoke(main, ["status"])
        assert result.exit_code == 0
        assert "enterprise" in result.output
        assert "Alice" in result.output
