from django.db import models
from django.utils import timezone


class Account(models.Model):
    class AccountType(models.TextChoices):
        CASH = 'cash', 'Cash'
        BANK = 'bank', 'Bank'
        MOBILE = 'mobile', 'Mobile Money'
        OTHER = 'other', 'Other'

    name = models.CharField(max_length=100)          # e.g. "Cash Till", "Stanbic Bank"
    account_type = models.CharField(
        max_length=20,
        choices=AccountType.choices,
        default=AccountType.CASH
    )
    balance = models.DecimalField(max_digits=15, decimal_places=2, default=0)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.name} ({self.get_account_type_display()})"

    def deposit(self, amount):
        self.balance += amount
        self.save()

    def withdraw(self, amount):
        if self.balance < amount:
            raise ValueError(f"Insufficient balance in {self.name}")
        self.balance -= amount
        self.save()


class AccountTransaction(models.Model):
    class TxType(models.TextChoices):
        SALE = 'sale', 'Sale'
        EXPENSE = 'expense', 'Expense'
        INCOME = 'income', 'Other Income'
        DRAW = 'draw', 'Owner Draw'
        TRANSFER = 'transfer', 'Transfer'
        ADJUSTMENT = 'adjustment', 'Adjustment'

    account = models.ForeignKey(
        Account, on_delete=models.PROTECT, related_name='transactions'
    )
    tx_type = models.CharField(max_length=20, choices=TxType.choices)
    amount = models.DecimalField(max_digits=15, decimal_places=2)
    direction = models.CharField(
        max_length=4,
        choices=[('in', 'Money In'), ('out', 'Money Out')]
    )
    description = models.CharField(max_length=255, blank=True)
    reference = models.CharField(max_length=100, blank=True)  # e.g. sale #, invoice #
    date = models.DateField(default=timezone.now)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.tx_type} | {self.direction} | {self.amount}"

class ExpenseCategory(models.Model):
    name = models.CharField(max_length=100)       # e.g. Rent, Salaries, Utilities
    description = models.TextField(blank=True)

    class Meta:
        verbose_name_plural = 'Expense Categories'

    def __str__(self):
        return self.name

# Expenses Module
class Expense(models.Model):
    category = models.ForeignKey(
        ExpenseCategory, on_delete=models.PROTECT, related_name='expenses'
    )
    account = models.ForeignKey(
        Account, on_delete=models.PROTECT, related_name='expenses'
    )
    amount = models.DecimalField(max_digits=15, decimal_places=2)
    description = models.CharField(max_length=255)
    reference = models.CharField(max_length=100, blank=True)   # receipt #, invoice #
    date = models.DateField(default=timezone.now)
    created_by = models.ForeignKey(
        'accounts.User', on_delete=models.SET_NULL, null=True, blank=True
    )
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.category.name} | {self.amount} | {self.date}"


class OtherIncome(models.Model):
    """Non-sale income — e.g. rent received, commission, refund."""
    account = models.ForeignKey(
        Account, on_delete=models.PROTECT, related_name='other_incomes'
    )
    amount = models.DecimalField(max_digits=15, decimal_places=2)
    description = models.CharField(max_length=255)
    reference = models.CharField(max_length=100, blank=True)
    date = models.DateField(default=timezone.now)
    created_by = models.ForeignKey(
        'accounts.User', on_delete=models.SET_NULL, null=True, blank=True
    )
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.description} | {self.amount} | {self.date}"


class OwnerDraw(models.Model):
    """Money owner takes out of the business personally."""
    account = models.ForeignKey(
        Account, on_delete=models.PROTECT, related_name='owner_draws'
    )
    amount = models.DecimalField(max_digits=15, decimal_places=2)
    description = models.CharField(max_length=255, blank=True)
    date = models.DateField(default=timezone.now)
    created_by = models.ForeignKey(
        'accounts.User', on_delete=models.SET_NULL, null=True, blank=True
    )
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Draw | {self.amount} | {self.date}"