from datetime import date
from decimal import Decimal

from django.contrib.auth import get_user_model
from django.test import TestCase, override_settings
from rest_framework import status
from rest_framework.test import APIClient

from apps.accounts.models import Account, AccountGroup
from apps.currencies.models import Currency
from apps.transactions.models import Transaction


@override_settings(
    STORAGES={
        "default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
        "staticfiles": {
            "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"
        },
    },
    WHITENOISE_AUTOREFRESH=True,
)
class AccountBalanceAPITests(TestCase):
    """Tests for the Account Balance API endpoint"""

    def setUp(self):
        """Set up test data"""
        User = get_user_model()
        self.user = User.objects.create_user(
            email="testuser@test.com", password="testpass123"
        )
        self.client = APIClient()
        self.client.force_authenticate(user=self.user)

        self.currency = Currency.objects.create(
            code="USD", name="US Dollar", decimal_places=2, prefix="$ "
        )
        self.account_group = AccountGroup.objects.create(name="Test Group")
        self.account = Account.objects.create(
            name="Test Account", group=self.account_group, currency=self.currency
        )

        # Create some transactions
        Transaction.objects.create(
            account=self.account,
            type=Transaction.Type.INCOME,
            amount=Decimal("500.00"),
            is_paid=True,
            date=date(2025, 1, 1),
            description="Paid income",
        )
        Transaction.objects.create(
            account=self.account,
            type=Transaction.Type.INCOME,
            amount=Decimal("200.00"),
            is_paid=False,
            date=date(2025, 1, 15),
            description="Unpaid income",
        )
        Transaction.objects.create(
            account=self.account,
            type=Transaction.Type.EXPENSE,
            amount=Decimal("100.00"),
            is_paid=True,
            date=date(2025, 1, 10),
            description="Paid expense",
        )

    def test_get_balance_success(self):
        """Test successful balance retrieval"""
        response = self.client.get(f"/api/accounts/{self.account.id}/balance/")

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn("current_balance", response.data)
        self.assertIn("projected_balance", response.data)
        self.assertIn("currency", response.data)

        # Current: 500 - 100 = 400
        self.assertEqual(Decimal(response.data["current_balance"]), Decimal("400.00"))
        # Projected: (500 + 200) - 100 = 600
        self.assertEqual(Decimal(response.data["projected_balance"]), Decimal("600.00"))

        # Check currency data
        self.assertEqual(response.data["currency"]["code"], "USD")

    def test_get_balance_nonexistent_account(self):
        """Test balance for non-existent account returns 404"""
        response = self.client.get("/api/accounts/99999/balance/")

        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

    def test_get_balance_unauthenticated(self):
        """Test unauthenticated request returns 401"""
        unauthenticated_client = APIClient()
        response = unauthenticated_client.get(
            f"/api/accounts/{self.account.id}/balance/"
        )

        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
