import pytest
from app.services.quota_service import (
    QuotaService,
    QuotaUsage,
    QuotaWarning,
    QuotaType,
    QUOTA_LIMITS,
    WARNING_THRESHOLDS,
)


class TestQuotaUsage:
    """额度使用数据结构测试"""

    def test_quota_usage_creation(self):
        """测试QuotaUsage数据创建"""
        usage = QuotaUsage(
            quota_type="api_calls",
            used=800,
            limit=1000,
            usage_percentage=80.0,
            status="warning",
            remaining=200,
        )
        assert usage.quota_type == "api_calls"
        assert usage.used == 800
        assert usage.limit == 1000
        assert usage.usage_percentage == 80.0
        assert usage.status == "warning"
        assert usage.remaining == 200

    def test_quota_usage_unlimited(self):
        """测试无限额度QuotaUsage"""
        usage = QuotaUsage(
            quota_type="api_calls",
            used=5000,
            limit=-1,
            usage_percentage=0.0,
            status="unlimited",
            remaining=-1,
        )
        assert usage.limit == -1
        assert usage.status == "unlimited"
        assert usage.remaining == -1


class TestQuotaWarning:
    """预警数据结构测试"""

    def test_quota_warning_creation(self):
        """测试QuotaWarning数据创建"""
        warning = QuotaWarning(
            quota_type="api_calls",
            status="warning",
            usage_percentage=80.0,
            message="API调用额度已使用80%",
            recommended_action="请关注使用情况，考虑升级套餐",
        )
        assert warning.quota_type == "api_calls"
        assert warning.status == "warning"
        assert warning.usage_percentage == 80.0
        assert "80%" in warning.message


class TestQuotaService:
    """额度预警服务测试"""

    @pytest.fixture
    def quota_service(self):
        """创建额度服务实例"""
        return QuotaService()

    def test_calculate_usage_percentage_basic(self, quota_service):
        """测试基础使用率计算"""
        percentage = quota_service.calculate_usage_percentage(used=800, limit=1000)
        assert percentage == 80.0

    def test_calculate_usage_percentage_zero(self, quota_service):
        """测试0%使用率"""
        percentage = quota_service.calculate_usage_percentage(used=0, limit=1000)
        assert percentage == 0.0

    def test_calculate_usage_percentage_full(self, quota_service):
        """测试100%使用率"""
        percentage = quota_service.calculate_usage_percentage(used=1000, limit=1000)
        assert percentage == 100.0

    def test_calculate_usage_percentage_half(self, quota_service):
        """测试50%使用率"""
        percentage = quota_service.calculate_usage_percentage(used=500, limit=1000)
        assert percentage == 50.0

    def test_calculate_usage_percentage_unlimited(self, quota_service):
        """测试无限额度使用率"""
        percentage = quota_service.calculate_usage_percentage(used=5000, limit=-1)
        assert percentage == 0.0

    def test_get_quota_status_ok(self, quota_service):
        """测试正常状态（低于80%）"""
        status = quota_service.get_quota_status(usage_percentage=50.0)
        assert status == "ok"

    def test_get_quota_status_warning(self, quota_service):
        """测试警告状态（80%）"""
        status = quota_service.get_quota_status(usage_percentage=80.0)
        assert status == "warning"

    def test_get_quota_status_critical(self, quota_service):
        """测试严重状态（90%）"""
        status = quota_service.get_quota_status(usage_percentage=90.0)
        assert status == "critical"

    def test_get_quota_status_exhausted(self, quota_service):
        """测试耗尽状态（100%）"""
        status = quota_service.get_quota_status(usage_percentage=100.0)
        assert status == "exhausted"

    def test_get_quota_status_unlimited(self, quota_service):
        """测试无限状态"""
        status = quota_service.get_quota_status(usage_percentage=0.0, limit=-1)
        assert status == "unlimited"

    def test_get_quota_limit_free_plan(self, quota_service):
        """测试免费套餐额度"""
        limit = quota_service.get_quota_limit("free", QuotaType.API_CALLS)
        assert limit == 1000

    def test_get_quota_limit_basic_plan(self, quota_service):
        """测试基础套餐额度"""
        limit = quota_service.get_quota_limit("basic", QuotaType.QUERIES)
        assert limit == 500

    def test_get_quota_limit_pro_plan(self, quota_service):
        """测试专业套餐额度"""
        limit = quota_service.get_quota_limit("pro", QuotaType.CONTENT_GENERATION)
        assert limit == 1000

    def test_get_quota_limit_unlimited_plan(self, quota_service):
        """测试无限套餐额度"""
        limit = quota_service.get_quota_limit("unlimited", QuotaType.API_CALLS)
        assert limit == -1

    def test_get_remaining_quota(self, quota_service):
        """测试剩余额度计算"""
        remaining = quota_service.get_remaining(used=800, limit=1000)
        assert remaining == 200

    def test_get_remaining_quota_exhausted(self, quota_service):
        """测试额度耗尽"""
        remaining = quota_service.get_remaining(used=1000, limit=1000)
        assert remaining == 0

    def test_get_remaining_quota_unlimited(self, quota_service):
        """测试无限额度"""
        remaining = quota_service.get_remaining(used=5000, limit=-1)
        assert remaining == -1

    def test_get_remaining_quota_overuse(self, quota_service):
        """测试超额使用"""
        remaining = quota_service.get_remaining(used=1200, limit=1000)
        assert remaining == -200

    def test_generate_warning_message_warning(self, quota_service):
        """测试生成警告消息"""
        warning = quota_service.generate_warning(
            quota_type=QuotaType.API_CALLS,
            status="warning",
            usage_percentage=80.0,
        )
        assert warning.quota_type == QuotaType.API_CALLS
        assert warning.status == "warning"
        assert warning.usage_percentage == 80.0
        assert "80%" in warning.message
        assert warning.recommended_action != ""

    def test_generate_warning_message_critical(self, quota_service):
        """测试生成严重警告消息"""
        warning = quota_service.generate_warning(
            quota_type=QuotaType.QUERIES,
            status="critical",
            usage_percentage=90.0,
        )
        assert warning.status == "critical"
        assert "90%" in warning.message

    def test_generate_warning_message_exhausted(self, quota_service):
        """测试生成耗尽警告消息"""
        warning = quota_service.generate_warning(
            quota_type=QuotaType.CONTENT_GENERATION,
            status="exhausted",
            usage_percentage=100.0,
        )
        assert warning.status == "exhausted"
        assert "100%" in warning.message

    def test_check_quota_free_plan(self, quota_service):
        """测试检查免费套餐额度"""
        usage = quota_service.check_quota(
            plan="free",
            quota_type=QuotaType.API_CALLS,
            used=800,
        )
        assert usage.quota_type == QuotaType.API_CALLS
        assert usage.limit == 1000
        assert usage.used == 800
        assert usage.remaining == 200
        assert usage.usage_percentage == 80.0
        assert usage.status == "warning"

    def test_check_quota_pro_plan_warning(self, quota_service):
        """测试专业套餐警告状态"""
        usage = quota_service.check_quota(
            plan="pro",
            quota_type=QuotaType.QUERIES,
            used=4500,
        )
        assert usage.limit == 5000
        assert usage.usage_percentage == 90.0
        assert usage.status == "critical"

    def test_check_quota_unlimited_plan(self, quota_service):
        """测试无限套餐"""
        usage = quota_service.check_quota(
            plan="unlimited",
            quota_type=QuotaType.API_CALLS,
            used=100000,
        )
        assert usage.limit == -1
        assert usage.status == "unlimited"
        assert usage.usage_percentage == 0.0
        assert usage.remaining == -1

    def test_check_quota_exhausted(self, quota_service):
        """测试额度耗尽"""
        usage = quota_service.check_quota(
            plan="free",
            quota_type=QuotaType.QUERIES,
            used=50,
        )
        assert usage.limit == 50
        assert usage.used == 50
        assert usage.remaining == 0
        assert usage.usage_percentage == 100.0
        assert usage.status == "exhausted"

    def test_check_quota_ok(self, quota_service):
        """测试额度正常"""
        usage = quota_service.check_quota(
            plan="basic",
            quota_type=QuotaType.STORAGE,
            used=500,
        )
        assert usage.limit == 1000
        assert usage.usage_percentage == 50.0
        assert usage.status == "ok"

    def test_reset_quota_usage(self, quota_service):
        """测试额度重置"""
        usage = quota_service.check_quota(
            plan="free",
            quota_type=QuotaType.API_CALLS,
            used=800,
        )
        assert usage.used == 800

        reset_usage = quota_service.reset_quota(used=800)
        assert reset_usage == 0

    def test_reset_quota_to_specific_value(self, quota_service):
        """测试重置到特定值"""
        reset_usage = quota_service.reset_quota(used=500, reset_to=100)
        assert reset_usage == 100

    def test_get_all_quota_usage(self, quota_service):
        """测试获取所有额度使用情况"""
        all_usage = quota_service.get_all_quota_usage(
            plan="free",
            api_calls_used=800,
            queries_used=40,
            content_generation_used=8,
            storage_used=50,
        )
        assert len(all_usage) == 4
        assert any(u.quota_type == QuotaType.API_CALLS and u.used == 800 for u in all_usage)
        assert any(u.quota_type == QuotaType.QUERIES and u.used == 40 for u in all_usage)

    def test_get_warnings_from_usage(self, quota_service):
        """测试从使用情况生成预警"""
        all_usage = quota_service.get_all_quota_usage(
            plan="free",
            api_calls_used=800,
            queries_used=45,
            content_generation_used=5,
            storage_used=20,
        )
        warnings = quota_service.get_warnings(all_usage)
        assert len(warnings) >= 1
        assert any(w.status in ["warning", "critical", "exhausted"] for w in warnings)

    def test_boundary_value_0_percent(self, quota_service):
        """测试边界值0%"""
        usage = quota_service.check_quota(
            plan="free",
            quota_type=QuotaType.API_CALLS,
            used=0,
        )
        assert usage.usage_percentage == 0.0
        assert usage.status == "ok"

    def test_boundary_value_100_percent(self, quota_service):
        """测试边界值100%"""
        usage = quota_service.check_quota(
            plan="free",
            quota_type=QuotaType.API_CALLS,
            used=1000,
        )
        assert usage.usage_percentage == 100.0
        assert usage.status == "exhausted"

    def test_warning_thresholds_constants(self):
        """测试预警阈值常量"""
        assert WARNING_THRESHOLDS["warning"] == 0.80
        assert WARNING_THRESHOLDS["critical"] == 0.90
        assert WARNING_THRESHOLDS["exhausted"] == 1.00

    def test_quota_limits_constants(self):
        """测试套餐额度常量"""
        assert QUOTA_LIMITS["free"]["api_calls"] == 1000
        assert QUOTA_LIMITS["free"]["queries"] == 50
        assert QUOTA_LIMITS["basic"]["api_calls"] == 10000
        assert QUOTA_LIMITS["pro"]["api_calls"] == 100000
        assert QUOTA_LIMITS["unlimited"]["api_calls"] == -1
