"""Tests for billing catalog, checkout flows, and usage ledger."""
from unittest.mock import AsyncMock, MagicMock
from uuid import uuid4

import pytest

from src.core.exceptions import NotFoundError
from src.domain.billing.catalog_service import BillingCatalogService
from src.domain.admin.models import SubscriptionPlan


# --- BillingCatalogService ---
@pytest.mark.asyncio
async def test_get_plan_by_slug_raises_when_not_found():
    plan_repo = AsyncMock()
    plan_repo.get_by_slug = AsyncMock(return_value=None)
    package_repo = AsyncMock()
    catalog = BillingCatalogService(plan_repo, package_repo)
    with pytest.raises(NotFoundError, match="not found"):
        await catalog.get_plan_by_slug("nonexistent")


@pytest.mark.asyncio
async def test_get_plan_by_slug_raises_when_inactive():
    plan = MagicMock(spec=SubscriptionPlan)
    plan.slug = "basic"
    plan.is_active = False
    plan_repo = AsyncMock()
    plan_repo.get_by_slug = AsyncMock(return_value=plan)
    package_repo = AsyncMock()
    catalog = BillingCatalogService(plan_repo, package_repo)
    with pytest.raises(NotFoundError, match="not active"):
        await catalog.get_plan_by_slug("basic")


@pytest.mark.asyncio
async def test_get_plan_by_slug_returns_plan():
    plan = MagicMock(spec=SubscriptionPlan)
    plan.slug = "pro"
    plan.is_active = True
    plan.stripe_monthly_price_id = "price_xxx"
    plan.stripe_yearly_price_id = "price_yyy"
    plan_repo = AsyncMock()
    plan_repo.get_by_slug = AsyncMock(return_value=plan)
    package_repo = AsyncMock()
    catalog = BillingCatalogService(plan_repo, package_repo)
    result = await catalog.get_plan_by_slug("pro")
    assert result.slug == "pro"
    assert catalog.resolve_stripe_price_id_for_plan(result, "month") == "price_xxx"
    assert catalog.resolve_stripe_price_id_for_plan(result, "year") == "price_yyy"


@pytest.mark.asyncio
async def test_resolve_stripe_price_id_raises_for_unknown_interval():
    plan = MagicMock()
    plan.slug = "pro"
    plan.stripe_monthly_price_id = "price_xxx"
    plan.stripe_yearly_price_id = None
    plan_repo = AsyncMock()
    package_repo = AsyncMock()
    catalog = BillingCatalogService(plan_repo, package_repo)
    with pytest.raises(ValueError, match="Unsupported billing interval"):
        catalog.resolve_stripe_price_id_for_plan(plan, "quarter")


@pytest.mark.asyncio
async def test_resolve_stripe_price_id_raises_when_missing():
    plan = MagicMock()
    plan.slug = "pro"
    plan.stripe_monthly_price_id = None
    plan_repo = AsyncMock()
    package_repo = AsyncMock()
    catalog = BillingCatalogService(plan_repo, package_repo)
    with pytest.raises(NotFoundError, match="no.*month"):
        catalog.resolve_stripe_price_id_for_plan(plan, "month")
