from datetime import date
from decimal import Decimal

from django.test import TestCase

from apps.accounts.models import User
from apps.business.wallet.models import (
    ConversionRule,
    MonthlyConversionLog,
    SuperCoinWallet,
    TDSLedger,
    Wallet,
)
from apps.business.wallet.services.conversion_service import monthly_conversion_job
from apps.business.wallet.services.reward_processor import apply_deductions
from apps.business.wallet.services.withdrawal_service import monthly_withdrawal_job
from apps.business.withdrawals.models import WithdrawalDeductionConfig, WithdrawalRequest


class WalletFinancialFlowTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(mobile="9999990001", email="wallet-tests@example.com", password="test@123")
        Wallet.objects.create(user=self.user, main_balance=Decimal("0.00"), repurchase_balance=Decimal("0.00"), voucher_balance=Decimal("0.00"))
        SuperCoinWallet.objects.create(user=self.user, balance=Decimal("0.00"))

    def test_apply_deductions_credits_supercoin_excluding_tds(self):
        WithdrawalDeductionConfig.objects.create(
            name="Test Config",
            tds_percent=Decimal("5.000"),
            repurchase_percent=Decimal("5.000"),
            welfare_fund_percent=Decimal("5.000"),
            technology_charges_percent=Decimal("5.000"),
            operations_charges_percent=Decimal("5.000"),
            is_active=True,
        )

        result = apply_deductions(Decimal("1000.00"))

        self.assertEqual(result["tds_amount"], Decimal("50.00"))
        self.assertEqual(result["internal_total"], Decimal("200.00"))
        self.assertEqual(result["super_coin_credit"], Decimal("800.00"))

    def test_monthly_conversion_respects_limits_and_logs_tds(self):
        WithdrawalDeductionConfig.objects.create(
            name="Conversion Config",
            tds_percent=Decimal("10.000"),
            repurchase_percent=Decimal("0.000"),
            welfare_fund_percent=Decimal("0.000"),
            technology_charges_percent=Decimal("0.000"),
            operations_charges_percent=Decimal("0.000"),
            is_active=True,
        )
        ConversionRule.objects.create(
            user=self.user,
            distributor_id="D-1001",
            monthly_limit=Decimal("300.00"),
            conversion_percentage=None,
            is_active=True,
        )

        super_wallet = SuperCoinWallet.objects.get(user=self.user)
        super_wallet.balance = Decimal("1000.00")
        super_wallet.save(update_fields=["balance", "updated_at"])

        result = monthly_conversion_job(run_date=date(2026, 4, 30), user=self.user)
        self.assertEqual(result["count"], 1)

        super_wallet.refresh_from_db()
        wallet = Wallet.objects.get(user=self.user)
        self.assertEqual(super_wallet.balance, Decimal("700.00"))
        self.assertEqual(wallet.main_balance, Decimal("270.00"))

        log = MonthlyConversionLog.objects.get(user=self.user, month=date(2026, 4, 1))
        self.assertEqual(log.converted_amount, Decimal("300.00"))
        self.assertEqual(log.tds_deducted, Decimal("30.00"))
        self.assertEqual(log.net_amount, Decimal("270.00"))

        tds = TDSLedger.objects.get(user=self.user, context=TDSLedger.Context.CONVERSION)
        self.assertEqual(tds.tds_amount, Decimal("30.00"))

    def test_monthly_withdrawal_job_creates_pending_request(self):
        wallet = Wallet.objects.get(user=self.user)
        wallet.main_balance = Decimal("500.00")
        wallet.locked_amount = Decimal("0.00")
        wallet.save(update_fields=["main_balance", "locked_amount"])

        result = monthly_withdrawal_job(run_date=date(2026, 4, 30), force=True)
        self.assertEqual(result["created"], 1)

        withdrawal = WithdrawalRequest.objects.get(user=self.user)
        self.assertEqual(withdrawal.status, WithdrawalRequest.Status.PENDING)
        self.assertEqual(withdrawal.amount_requested, Decimal("500.00"))
