"""
Tests for django_stripe_billing.utils.

Covers str_to_number, number_to_currency, and fire_outgoing_webhook (mocked).
"""
import pytest
from unittest.mock import patch, MagicMock
from django.test import override_settings

from django_stripe_billing.utils import (
    str_to_number,
    number_to_currency,
    fire_outgoing_webhook,
)


class TestStrToNumber:
    """str_to_number converts Stripe integer amount to decimal string."""

    def test_zero_returns_zero_dot_zero_zero(self):
        assert str_to_number(0) == "0.00"
        assert str_to_number("0") == "0.00"

    def test_single_digit_cents(self):
        assert str_to_number(5) == "0.05"
        assert str_to_number(9) == "0.09"

    def test_two_digit_cents(self):
        assert str_to_number(10) == "0.10"
        assert str_to_number(99) == "0.99"

    def test_standard_amounts(self):
        assert str_to_number(1234) == "12.34"
        assert str_to_number("1234") == "12.34"
        assert str_to_number(10000) == "100.00"

    def test_empty_or_invalid_returns_zero_dot_zero_zero(self):
        assert str_to_number("") == "0.00"
        assert str_to_number("   ") == "0.00"
        assert str_to_number("-") == "0.00"

    def test_whitespace_stripped(self):
        assert str_to_number("  1234  ") == "12.34"


class TestNumberToCurrency:
    """number_to_currency formats amount with currency symbol."""

    def test_gbp(self):
        assert number_to_currency(1234, "gbp") == "£12.34"
        assert number_to_currency(1234, "GBP") == "£12.34"

    def test_usd(self):
        assert number_to_currency(999, "usd") == "$9.99"

    def test_eur(self):
        assert number_to_currency(500, "eur") == "€5.00"

    def test_unknown_currency_uses_code(self):
        result = number_to_currency(100, "jpy")
        assert "1.00" in result  # 100 cents = 1.00
        assert "JPY" in result or "jpy" in result

    def test_small_amount(self):
        assert number_to_currency(5, "gbp") == "£0.05"


class TestFireOutgoingWebhook:
    """fire_outgoing_webhook POSTs to configured URL or is no-op when empty."""

    def test_no_op_when_no_url_configured_for_event_type(self):
        with patch("django_stripe_billing.utils.requests.post") as mock_post:
            with override_settings(
                STRIPE_BILLING={"OUTGOING_WEBHOOK_URLS": {}}
            ):
                fire_outgoing_webhook("invoice.payment_succeeded", {"foo": "bar"})
            mock_post.assert_not_called()

    def test_no_op_when_url_empty_for_event_type(self):
        with patch("django_stripe_billing.utils.requests.post") as mock_post:
            with override_settings(
                STRIPE_BILLING={
                    "OUTGOING_WEBHOOK_URLS": {"invoice.payment_succeeded": ""},
                }
            ):
                fire_outgoing_webhook("invoice.payment_succeeded", {"foo": "bar"})
            mock_post.assert_not_called()

    def test_posts_json_when_url_configured(self):
        with patch("django_stripe_billing.utils.requests.post") as mock_post:
            mock_post.return_value = MagicMock(status_code=200)
            with override_settings(
                STRIPE_BILLING={
                    "OUTGOING_WEBHOOK_URLS": {
                        "invoice.payment_succeeded": "https://hooks.example.com/invoice",
                    },
                    "ENVIRONMENT": "test",
                    "APP_TITLE": "TestApp",
                }
            ):
                fire_outgoing_webhook(
                    "invoice.payment_succeeded",
                    {"customer_id": "cus_123", "amount_paid": 1000},
                )
            mock_post.assert_called_once()
            call_kw = mock_post.call_args[1]
            assert call_kw["json"]["event_type"] == "invoice.payment_succeeded"
            assert call_kw["json"]["customer_id"] == "cus_123"
            assert "timestamp" in call_kw["json"]
            assert call_kw["json"]["environment"] == "test"
            assert call_kw["headers"]["Content-Type"] == "application/json"
