"""Tests for billing and usage endpoints."""

from unittest.mock import patch


class TestUsageEndpoint:
    """Tests for GET /v1/usage."""

    def test_get_usage_success(self, client, auth_header):
        with patch("api.db.get_usage") as mock_usage, \
             patch("api.db.get_plan_limits") as mock_limits:
            mock_usage.return_value = {"runs_count": 42, "fixes_count": 3}
            mock_limits.return_value = {
                "runs_limit": 100, "fixes_limit": 20, "retention_days": 30,
            }
            response = client.get("/v1/usage", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert data["runs_used"] == 42
            assert data["runs_limit"] == 100
            assert data["fixes_used"] == 3
            assert "period_start" in data
            assert "period_end" in data

    def test_get_usage_unauthorized(self, client):
        response = client.get("/v1/usage")
        assert response.status_code == 401


class TestCheckoutEndpoint:
    """Tests for POST /v1/billing/checkout."""

    def test_create_checkout_success(self, client, auth_header):
        with patch("api.billing.create_checkout_session") as mock_checkout:
            mock_checkout.return_value = {
                "session_id": "cs_test_123",
                "url": "https://checkout.stripe.com/session/cs_test_123",
            }
            response = client.post(
                "/v1/billing/checkout",
                json={
                    "price_id": "price_pro_monthly",
                    "success_url": "https://app.hikaflow.com/billing/success",
                    "cancel_url": "https://app.hikaflow.com/billing/cancel",
                },
                headers=auth_header,
            )
            assert response.status_code == 200
            data = response.json()
            assert data["session_id"] == "cs_test_123"
            assert "url" in data

    def test_create_checkout_invalid_price(self, client, auth_header):
        with patch("api.billing.create_checkout_session") as mock_checkout:
            mock_checkout.side_effect = ValueError("Invalid price_id")
            response = client.post(
                "/v1/billing/checkout",
                json={
                    "price_id": "invalid_price",
                    "success_url": "https://app.hikaflow.com/success",
                    "cancel_url": "https://app.hikaflow.com/cancel",
                },
                headers=auth_header,
            )
            assert response.status_code == 400

    def test_create_checkout_unauthorized(self, client):
        response = client.post(
            "/v1/billing/checkout",
            json={
                "price_id": "price_pro_monthly",
                "success_url": "https://app.hikaflow.com/success",
                "cancel_url": "https://app.hikaflow.com/cancel",
            },
        )
        assert response.status_code == 401


class TestPortalEndpoint:
    """Tests for POST /v1/billing/portal."""

    def test_create_portal_success(self, client, auth_header):
        with patch("api.billing.create_portal_session") as mock_portal:
            mock_portal.return_value = {
                "url": "https://billing.stripe.com/session/portal_123",
            }
            response = client.post(
                "/v1/billing/portal",
                json={"return_url": "https://app.hikaflow.com/billing"},
                headers=auth_header,
            )
            assert response.status_code == 200
            assert "url" in response.json()

    def test_create_portal_unauthorized(self, client):
        response = client.post(
            "/v1/billing/portal",
            json={"return_url": "https://app.hikaflow.com/billing"},
        )
        assert response.status_code == 401


class TestSubscriptionEndpoint:
    """Tests for GET /v1/billing/subscription."""

    def test_get_subscription_active(self, client, auth_header):
        with patch("api.billing.get_subscription") as mock_sub:
            mock_sub.return_value = {
                "id": "sub_123",
                "plan": "pro",
                "status": "active",
                "current_period_end": 1700000000,
                "cancel_at_period_end": False,
            }
            response = client.get("/v1/billing/subscription", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert data["plan"] == "pro"
            assert data["status"] == "active"

    def test_get_subscription_free(self, client, auth_header):
        with patch("api.billing.get_subscription") as mock_sub:
            mock_sub.return_value = None
            response = client.get("/v1/billing/subscription", headers=auth_header)
            assert response.status_code == 200
            data = response.json()
            assert data["plan"] == "free"
            assert data["status"] == "active"

    def test_get_subscription_unauthorized(self, client):
        response = client.get("/v1/billing/subscription")
        assert response.status_code == 401


class TestCancelSubscription:
    """Tests for POST /v1/billing/cancel."""

    def test_cancel_subscription_success(self, client, auth_header):
        with patch("api.billing.cancel_subscription") as mock_cancel:
            mock_cancel.return_value = {"status": "canceled_at_period_end"}
            response = client.post("/v1/billing/cancel", headers=auth_header)
            assert response.status_code == 200
            assert response.json()["status"] == "canceled_at_period_end"

    def test_cancel_subscription_no_active(self, client, auth_header):
        with patch("api.billing.cancel_subscription") as mock_cancel:
            mock_cancel.side_effect = ValueError("No active subscription found")
            response = client.post("/v1/billing/cancel", headers=auth_header)
            assert response.status_code == 400

    def test_cancel_subscription_unauthorized(self, client):
        response = client.post("/v1/billing/cancel")
        assert response.status_code == 401
