from django.test import TestCase
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from .models import Wallet, LedgerEntry, Terminal, IdempotencyKey
from .services import simulate_deposit, post_transfer

class LedgerTests(TestCase):
    def setUp(self):
        self.a = User.objects.create_user("alice", password="StrongPass123!")
        self.b = User.objects.create_user("bob", password="StrongPass123!")
        Wallet.objects.create(user=self.a, asset="TZS")
        Wallet.objects.create(user=self.b, asset="TZS")
    def test_transfer_balances_ledger(self):
        simulate_deposit(self.a, "TZS", 10000)
        post_transfer(self.a, self.b, "TZS", 2500)
        self.assertEqual(Wallet.objects.get(user=self.a, asset="TZS").balance_minor, 7500)
        self.assertEqual(Wallet.objects.get(user=self.b, asset="TZS").balance_minor, 2500)
        entries = LedgerEntry.objects.filter(transaction__kind="transfer")
        self.assertEqual(sum(e.amount_minor for e in entries.filter(direction="debit")), 2500)
        self.assertEqual(sum(e.amount_minor for e in entries.filter(direction="credit")), 2500)
    def test_idempotent_transfer_returns_same_transaction(self):
        simulate_deposit(self.a, "TZS", 10000)
        first = post_transfer(self.a, self.b, "TZS", 2500, idempotency_key="test-key-1")
        second = post_transfer(self.a, self.b, "TZS", 2500, idempotency_key="test-key-1")
        self.assertEqual(first.pk, second.pk)
        self.assertEqual(IdempotencyKey.objects.filter(user=self.a, key="test-key-1").count(), 1)
        self.assertEqual(Wallet.objects.get(user=self.a, asset="TZS").balance_minor, 7500)

    def test_reusing_idempotency_key_with_different_request_is_rejected(self):
        simulate_deposit(self.a, "TZS", 10000)
        post_transfer(self.a, self.b, "TZS", 2500, idempotency_key="test-key-2")
        with self.assertRaises(ValidationError):
            post_transfer(self.a, self.b, "TZS", 3000, idempotency_key="test-key-2")

    def test_insufficient_funds_rejected(self):
        with self.assertRaises(ValidationError):
            post_transfer(self.a, self.b, "TZS", 1)


from .models import Terminal
from .forms import TerminalForm

class TerminalConfigurationTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user("terminaluser", password="StrongPass123!")

    def test_default_terminal_values(self):
        terminal = Terminal.objects.create(owner=self.user)
        self.assertEqual(terminal.terminal_id, "TERM-000001")
        self.assertEqual(terminal.protocol, "HTTPS")
        self.assertEqual(str(terminal.ip_address), "127.0.0.1")
        self.assertEqual(terminal.dns_name, "localhost")
        self.assertEqual(terminal.machine_os, "Windows 11")
        self.assertEqual(terminal.port, 8000)
        self.assertEqual(str(terminal.min_receiving_usd), "10.00")
        self.assertEqual(str(terminal.max_receiving_usd), "1000000.00")

    def test_rejects_maximum_below_minimum(self):
        form = TerminalForm({
            "terminal_id": "TERM-000002", "protocol": "HTTPS",
            "ip_address": "127.0.0.1", "dns_name": "localhost",
            "machine_os": "Windows 11", "port": 8000,
            "min_receiving_usd": "100", "max_receiving_usd": "10",
        })
        self.assertFalse(form.is_valid())
