"""Tests for checkout session creation."""

from __future__ import annotations

from unittest.mock import MagicMock, patch

import pytest
from billing.checkout import create_checkout, create_portal_session
from billing.models import CheckoutSession


class TestCreateCheckout:
    """Tests for create_checkout function."""

    @patch("billing.checkout.stripe.checkout.Session.create")
    def test_creates_session_with_correct_params(self, mock_create: MagicMock) -> None:
        mock_create.return_value = MagicMock(
            url="https://checkout.stripe.com/c/pay_test123",
            id="cs_test_session123",
        )

        result = create_checkout(user_id="user_abc", plan="pro", email="user@example.com")

        assert isinstance(result, CheckoutSession)
        assert result.url == "https://checkout.stripe.com/c/pay_test123"
        assert result.session_id == "cs_test_session123"

        call_kwargs = mock_create.call_args[1]
        assert call_kwargs["mode"] == "subscription"
        assert call_kwargs["line_items"] == [{"price": "price_pro_test", "quantity": 1}]
        assert call_kwargs["client_reference_id"] == "user_abc"
        assert call_kwargs["customer_email"] == "user@example.com"
        assert call_kwargs["success_url"] == "https://example.com/success"
        assert call_kwargs["cancel_url"] == "https://example.com/cancel"
        assert call_kwargs["metadata"]["user_id"] == "user_abc"
        assert call_kwargs["metadata"]["plan"] == "pro"

    @patch("billing.checkout.stripe.checkout.Session.create")
    def test_creates_session_without_email(self, mock_create: MagicMock) -> None:
        mock_create.return_value = MagicMock(
            url="https://checkout.stripe.com/c/pay_test456",
            id="cs_test_session456",
        )

        result = create_checkout(user_id="user_xyz", plan="starter")

        assert result.session_id == "cs_test_session456"

        call_kwargs = mock_create.call_args[1]
        assert "customer_email" not in call_kwargs

    def test_raises_value_error_for_unknown_plan(self) -> None:
        with pytest.raises(ValueError, match="Unknown plan 'nonexistent'"):
            create_checkout(user_id="user_abc", plan="nonexistent")

    def test_error_message_lists_available_plans(self) -> None:
        with pytest.raises(ValueError, match="starter") as exc_info:
            create_checkout(user_id="user_abc", plan="bad_plan")
        assert "pro" in str(exc_info.value)
        assert "enterprise" in str(exc_info.value)


class TestCreatePortalSession:
    """Tests for create_portal_session function."""

    @patch("billing.checkout.stripe.billing_portal.Session.create")
    def test_returns_portal_url(self, mock_create: MagicMock) -> None:
        mock_create.return_value = MagicMock(
            url="https://billing.stripe.com/p/session/test_portal",
        )

        url = create_portal_session(customer_id="cus_test123")

        assert url == "https://billing.stripe.com/p/session/test_portal"
        mock_create.assert_called_once_with(
            customer="cus_test123",
            return_url="https://example.com/success",
        )
