import uuid

from django.db import models

from core.models import Project, TimeStampedModel


class BankAccount(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    project = models.ForeignKey(
        Project, on_delete=models.DO_NOTHING, related_name="bank_accounts",
        db_constraint=False,  # Project lives in the shared platform DB, not this company DB
    )
    bank_name = models.CharField(max_length=150)
    account_number = models.CharField(max_length=50, blank=True)
    branch = models.CharField(max_length=150, blank=True)
    opening_balance = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    is_active = models.BooleanField(default=True)

    class Meta:
        db_table = "finance_bank_account"
        ordering = ["bank_name"]

    def __str__(self):
        return f"{self.bank_name} - {self.account_number}"

    @property
    def total_deposits(self):
        return self.transactions.filter(txn_type="deposit").aggregate(t=models.Sum("amount"))["t"] or 0

    @property
    def total_withdrawals(self):
        return self.transactions.filter(txn_type="withdrawal").aggregate(t=models.Sum("amount"))["t"] or 0

    @property
    def current_balance(self):
        return self.opening_balance + self.total_deposits - self.total_withdrawals


class BankTransaction(TimeStampedModel):
    TXN_TYPE_CHOICES = [
        ("deposit", "Deposit"),
        ("withdrawal", "Withdrawal"),
        ("transfer_out", "Transfer Out"),
        ("transfer_in", "Transfer In"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    bank_account = models.ForeignKey(BankAccount, on_delete=models.CASCADE, related_name="transactions")
    date = models.DateField()
    txn_type = models.CharField(max_length=15, choices=TXN_TYPE_CHOICES)
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    remarks = models.CharField(max_length=255, blank=True)

    class Meta:
        db_table = "finance_bank_txn"
        ordering = ["-date", "-created_at"]

    def __str__(self):
        return f"{self.bank_account.bank_name} {self.txn_type} {self.amount} on {self.date}"

    @property
    def project(self):
        return self.bank_account.project

    def save(self, *args, **kwargs):
        # Deposits & transfer-in increase balance; withdrawal / transfer-out decreases it.
        if self.txn_type in ("withdrawal", "transfer_out"):
            self.amount = abs(self.amount)
        super().save(*args, **kwargs)


class CashTransaction(TimeStampedModel):
    TXN_TYPE_CHOICES = [("in", "Cash In"), ("out", "Cash Out")]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    project = models.ForeignKey(
        Project, on_delete=models.DO_NOTHING, related_name="cash_transactions",
        db_constraint=False,  # Project lives in the shared platform DB, not this company DB
    )
    date = models.DateField()
    txn_type = models.CharField(max_length=5, choices=TXN_TYPE_CHOICES)
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    source_or_purpose = models.CharField(max_length=255, blank=True)
    remarks = models.CharField(max_length=255, blank=True)

    class Meta:
        db_table = "finance_cash_txn"
        ordering = ["-date", "-created_at"]

    def __str__(self):
        return f"Cash {self.txn_type} {self.amount} on {self.date}"
