from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.contrib.auth.models import User
from django.db import transaction
from datetime import date
from django.db.models import F, Sum
from django.core.exceptions import ValidationError
import qrcode
import barcode
from barcode.writer import ImageWriter
from io import BytesIO
from django.core.files import File
from PIL import Image, ImageDraw
from django.utils import timezone
from django.conf import settings


class Currency(models.Model):
    class Meta:
        verbose_name = 'Currency'
        verbose_name_plural = 'Currency'
    name = models.CharField(max_length=50)
    code = models.CharField(max_length=50)
    symbol = models.CharField(max_length=50)

    def __str__(self):
        return self.code


class Address(models.Model):
    street = models.CharField(max_length=255, default='N/A')
    city = models.CharField(max_length=255, default='Kabul')
    State_province_area = models.CharField(max_length=255, default='N/A')
    postal_code = models.CharField(max_length=255, default='N/A')
    country = models.CharField(max_length=255, default='Afghanistan')

    def __str__(self):
        return f'{self.street}, {self.city}, {self.State_province_area}, {self.postal_code}, {self.country}'


class Sender(models.Model):
    name = models.CharField(max_length=255, help_text='John')
    last_name = models.CharField(max_length=255, help_text='Besos')
    fathers_name = models.CharField(max_length=255, help_text='Bruc')
    address = models.ForeignKey(
        Address, on_delete=models.PROTECT, blank=True, null=True, help_text='open address window')
    mobile = models.CharField(
        max_length=20, help_text='numeric till 13 number')
    email = models.EmailField(default='example@domain.com')
    home_phone = models.CharField(max_length=13, default='N/A')
    street = models.CharField(max_length=255, default='N/A')
    city = models.CharField(max_length=255, default='Kabul')
    State_province_area = models.CharField(max_length=255, default='N/A')
    postal_code = models.CharField(max_length=255, default='N/A')
    country = models.CharField(max_length=255, default='Afghanistan')

    def __str__(self):
        return f'{self.id}-{self.name} - {self.last_name}'


class SenderDocuments(models.Model):
    document = models.ForeignKey(
        Sender, on_delete=models.CASCADE, related_name='documents')
    document_title = models.CharField(
        max_length=255, help_text='name your document')
    image = models.ImageField(
        upload_to='cargo/sender/documents',)

    class Meta:
        verbose_name = 'Sender Document'
        verbose_name_plural = 'Sender Documents'

    def __str__(self):
        return f'{self.document}'


class Receiver(models.Model):
    name = models.CharField(max_length=255, help_text='John')
    last_name = models.CharField(max_length=255, help_text='Besos')
    fathers_name = models.CharField(max_length=255, help_text='Bruc')
    address = models.ForeignKey(
        Address, on_delete=models.PROTECT, blank=True, null=True, help_text='open address window')
    mobile = models.CharField(
        max_length=13, help_text='numeric till 13 number')
    email = models.EmailField(default='example@gmail.com')
    home_phone = models.CharField(max_length=13, default='N/A')
    street = models.CharField(max_length=255, default='N/A')
    city = models.CharField(max_length=255, default='Kabul')
    State_province_area = models.CharField(max_length=255, default='N/A')
    postal_code = models.CharField(max_length=255, default='N/A')
    country = models.CharField(max_length=255, default='Afghanistan')

    def __str__(self):
        return f'{self.id}-{self.name} - {self.last_name}'


class ReceiverDocuments(models.Model):
    document = models.ForeignKey(
        Receiver, on_delete=models.CASCADE, related_name='receiver_documents')
    document_title = models.CharField(
        max_length=255, help_text='name your document')
    image = models.ImageField(
        upload_to='cargo/receiver/documents',)

    class Meta:
        verbose_name = 'Recever Document'
        verbose_name_plural = 'Receiver Documents'

    def __str__(self):
        return f'{self.document}'


class SenderBalance(models.Model):
    tx_date = models.DateTimeField(auto_created=True)
    sender = models.ForeignKey(Sender, on_delete=models.CASCADE)
    tx_number = models.CharField(max_length=255)
    description = models.CharField(max_length=255, default='N/A')
    previous_balance = models.DecimalField(
        max_digits=10, decimal_places=2, validators=[MinValueValidator(0)], default=0)
    amount_in = models.DecimalField(max_digits=10, decimal_places=2, validators=[
                                    MinValueValidator(0)], default=0)
    amount_out = models.DecimalField(max_digits=10, decimal_places=2, validators=[
        MinValueValidator(0)], default=0)
    current_balance = models.DecimalField(max_digits=10, decimal_places=2, validators=[
        MinValueValidator(0)], default=0)
    remarks = models.CharField(max_length=255, default='N/A')

    def __str__(self):
        return f'{self.sender} - {self.tx_number}'


class MeasurementUnit(models.Model):
    title = models.CharField(max_length=255)
    details = models.CharField(max_length=255, default='N/A')

    def __str__(self):
        return self.title


class Item(models.Model):
    title = models.CharField(max_length=255)
    measurement_unit = models.ForeignKey(
        MeasurementUnit, on_delete=models.PROTECT)
    details = models.CharField(max_length=255, default='N/A')
    created_at = models.DateTimeField(default=timezone.now)  # 👈 add this line

    class Meta:
        permissions = [
            ("bulk_delete", "Can delete bulk?"),
            ("download_pdf", "Can download PDF?"),
            ("download_excel", "Can download Excel?"),
        ]

    def __str__(self):
        return self.title


class CargoBy(models.Model):
    title = models.CharField(max_length=255)
    incharge = models.CharField(max_length=255)
    phone = models.CharField(max_length=255)
    address = models.CharField(max_length=255, default='N/A')
    logo = models.ImageField(upload_to='cargo/by/log',)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = 'Cargo By'
        verbose_name_plural = 'Cargo By'


class CargoByBalance(models.Model):
    tx_date = models.DateTimeField(auto_created=True)
    cargo_by = models.ForeignKey(CargoBy, on_delete=models.CASCADE)
    tx_number = models.CharField(max_length=255)
    description = models.CharField(max_length=255, default='N/A')
    previous_balance = models.DecimalField(
        max_digits=10, decimal_places=2, validators=[MinValueValidator(0)], default=0)
    amount_in = models.DecimalField(max_digits=10, decimal_places=2, validators=[
                                    MinValueValidator(0)], default=0)
    amount_out = models.DecimalField(max_digits=10, decimal_places=2, validators=[
        MinValueValidator(0)], default=0)
    current_balance = models.DecimalField(max_digits=10, decimal_places=2, validators=[
        MinValueValidator(0)], default=0)
    remarks = models.CharField(max_length=255, default='N/A')

    def __str__(self):
        return f'{self.cargo_by} - {self.tx_number}'


class Invoice(models.Model):
    sender = models.ForeignKey(Sender, on_delete=models.PROTECT)
    receiver = models.ForeignKey(Receiver, on_delete=models.PROTECT)
    by_cargo = models.ForeignKey(CargoBy, on_delete=models.PROTECT)
    destination = models.CharField(max_length=255, default='N/A')
    item_value = models.DecimalField(
        max_digits=15, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    item_description = models.TextField(default='N/A')
    amount_paid = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    remain_amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    total_amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    remarks = models.CharField(max_length=255, default='N/A')
    track_number = models.CharField(max_length=255, default='N/A')
    created_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='invoice_created', null=True)
    updated_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='invoice_updated', null=True)
    created_at = models.DateTimeField(
        auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    qr_code = models.ImageField(
        upload_to='invoice/qr_codes/', blank=True, null=True)
    barcode_image = models.ImageField(
        upload_to='invoice/barcodes/', blank=True, null=True)

    class Meta:
        permissions = [
            ("invoice_bulk_delete", "Can delete bulk?"),
            ("invoice_download_pdf", "Can download PDF?"),
            ("invoice_download_excel", "Can download Excel?"),
            ("sales_report", "Can see sales report?"),
            ("print_invoice", "Can print invoice?"),
            ("print_slip", "Can print delivery slip?"),
        ]

    def __str__(self):
        return f'Invoice #{self.id} of {self.sender}'

    # ----------------------------  the start of instance of sender balanec ------------------------------
    # QR Code generation
    def generate_qr_code(self):
        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_L,
            box_size=10,
            border=4,
        )
        qr_data = f'Invoice ID: {self.id}\nSender: {self.sender}\nTotal Amount: {self.total_amount}'
        qr.add_data(qr_data)
        qr.make(fit=True)

        # Create an image from the QR Code instance
        img = qr.make_image(fill='black', back_color='white')

        # Save the image to a BytesIO object
        buffer = BytesIO()
        img.save(buffer, format="PNG")
        file_name = f'invoice_qr_{self.id}.png'

        # Save the QR code image to the model field
        self.qr_code.save(file_name, File(buffer), save=False)

    def generate_barcode(self):
        from barcode import Code128
        from barcode.writer import ImageWriter
        from PIL import Image
        import io

        barcode_data = str(self.id)  # or any custom string
        buffer = BytesIO()

        # Step 1: Generate barcode at high DPI
        writer = ImageWriter()
        writer.set_options({
            'module_width': 0.2,
            'module_height': 20.0,
            'font_size': 0,
            'quiet_zone': 2.0,
            'dpi': 300
        })

        barcode = Code128(barcode_data, writer=writer)
        barcode.write(buffer)

        # Step 2: Resize to 4 cm × 1.5 cm @ 300 DPI = 472 × 177 pixels
        buffer.seek(0)
        img = Image.open(buffer)

        target_size = (472, 177)
        resized_img = img.resize(target_size, Image.Resampling.LANCZOS)

        # Step 3: Save the resized barcode image
        final_buffer = BytesIO()
        resized_img.save(final_buffer, format='PNG')
        file_name = f'barcode_{self.id}.png'
        self.barcode_image.save(file_name, File(final_buffer), save=False)

        buffer.close()
        final_buffer.close()

    def calculate_remain_amount(self):
        invoice_items = InvoiceItems.objects.filter(invoice_id=self)
        total_payable_amount = sum(
            item.sender_payable_amount for item in invoice_items)
        remain_amount = total_payable_amount - self.amount_paid
        return max(remain_amount, 0)

    def cargo_delivery_charges(self):
        return sum(item.cargo_delivery_charges for item in self.invoiceitems_set.all())

    def calculate_total_amount(self):
        invoice_items = InvoiceItems.objects.filter(invoice_id=self)
        total_amount = sum(
            item.sender_payable_amount for item in invoice_items)
        total_amount = total_amount
        return max(total_amount, 0)

    def calculate_expo_amount(self):
        return sum(item.expo_amount for item in self.invoiceitems_set.all())

    def save(self, *args, **kwargs):
        # First save the invoice to generate a primary key (id)
        if not self.pk:
            super().save(*args, **kwargs)  # Save to generate the pk

        # Now calculate the totals after the invoice is saved
        self.total_amount = self.calculate_total_amount()
        self.remain_amount = self.calculate_remain_amount()
        # Generate QR code and barcode after the instance has an ID
        self.generate_qr_code()
        self.generate_barcode()

        # Save the invoice again with the calculated totals
        with transaction.atomic():
            super().save(*args, **kwargs)

            # Remaining balance calculations for sender and cargo
            amount_in = self.total_amount
            amount_out = self.amount_paid
            amount_in_cargo = self.calculate_expo_amount()
            cargo_delivery_charge = self.cargo_delivery_charges()
            amount_out_cargo = 0
            current_date = date.today()

            # Retrieve the previous balance of sender
            ca_previous_balance = SenderBalance.objects.filter(
                sender=self.sender
            ).order_by('-id').values('current_balance').first()
            ca_previous_balance = ca_previous_balance['current_balance'] if ca_previous_balance else 0

            # Calculate the current balance sender
            ca_current_balance = ca_previous_balance + (amount_in - amount_out)

            # Retrieve the previous balance cargo
            cargo_previous_balance = CargoByBalance.objects.filter(
                cargo_by=self.by_cargo
            ).order_by('-id').values('current_balance').first()
            cargo_previous_balance = cargo_previous_balance[
                'current_balance'] if cargo_previous_balance else 0

            # Calculate the current balance cargo
            cargo_current_balance = cargo_previous_balance + \
                (amount_in_cargo - amount_out_cargo)

            # Check if a SenderBalance already exists
            existing_sender_account = SenderBalance.objects.filter(
                tx_number=f'CB00{self.id}'
            ).first()

            # Check if a CargoByBalance already exists
            existing_cargo_account = CargoByBalance.objects.filter(
                tx_number=f'POB00{self.id}'
            ).first()

            if amount_in > 0 and not existing_sender_account:
                # Create a new instance of SenderBalance
                sender_account = SenderBalance(
                    tx_date=current_date,
                    sender=self.sender,
                    tx_number=f'CB00{self.id}',
                    description=f'account credited for {self.sender} against the remain amount of bill no: {self.id} payment!',
                    amount_in=amount_in,
                    amount_out=amount_out,
                    previous_balance=ca_previous_balance,
                    current_balance=ca_current_balance,
                    remarks=f'account credited for {self.sender} against bill no: {self.id} payment!'
                )
                sender_account.save()

            if amount_in_cargo > 0 and not existing_cargo_account:
                # Create a new instance of CargoByBalance
                cargo_by_account = CargoByBalance(
                    tx_date=current_date,
                    cargo_by=self.by_cargo,
                    tx_number=f'POB00{self.id}',
                    description=f'account credited for {self.by_cargo} against the bill no: {self.id} for percentage payment!',
                    amount_in=amount_in_cargo,
                    amount_out=amount_out_cargo,
                    previous_balance=cargo_previous_balance,
                    current_balance=cargo_current_balance,
                    remarks=f'account credited for {self.by_cargo} against bill no: {self.id} payment!'
                )
                cargo_by_account.save()

                # Create a new instance of CargoByBalance for cargo delivery charges
                cargo_by_account_delivery_charge = CargoByBalance(
                    tx_date=current_date,
                    cargo_by=self.by_cargo,
                    tx_number=f'DCOBN00{self.id}',
                    description=f'account credited for {self.by_cargo} against cargo delivery charge for bill no: {self.id} payment!',
                    amount_in=cargo_delivery_charge,
                    amount_out=0,
                    previous_balance=cargo_previous_balance,
                    current_balance=cargo_current_balance,
                    remarks=f'account credited for {self.by_cargo} against cargo delivery charge for bill no: {self.id} payment!'
                )
                cargo_by_account_delivery_charge.save()

        super().save(*args, **kwargs)

        # ---------------------------- The End of sender balance instance -------------------------------------


class InvoiceItems(models.Model):
    invoice_id = models.ForeignKey(Invoice, on_delete=models.CASCADE)
    item = models.ForeignKey(Item, on_delete=models.PROTECT)
    dimention = models.PositiveIntegerField(default=0)
    quantity = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    unit_price = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    AWB_Fee = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    discount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    deliver_charges = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    handling_charges = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    net_profit = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    expo_percentage = models.DecimalField(
        max_digits=5, decimal_places=2, default=0, validators=[MinValueValidator(0)])

    def __str__(self):
        return f'{self.item}'

    @property
    def total_amount(self):
        return self.quantity * self.unit_price + self.handling_charges

    @property
    def dimensions_total(self):
        return self.dimention * self.unit_price

    @property
    def sender_payable_amount(self):
        return (self.total_amount + self.dimensions_total+self.AWB_Fee) - self.discount

    @property
    def net_amount(self):
        return ((self.total_amount + self.dimensions_total+self.AWB_Fee) - self.discount)-self.deliver_charges

    @property
    def expo_amount(self):
        return (self.net_amount / 100) * self.expo_percentage

    @property
    def cargo_delivery_charges(self):
        return (self.deliver_charges)


class PaymentToExpo(models.Model):
    expo = models.ForeignKey(CargoBy, on_delete=models.PROTECT)
    amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    remain_amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    remarks = models.CharField(max_length=255, default='N/A')
    created_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='payment_to_expo_created', null=True)
    updated_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='payment_to_expo_updated', null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f'{self.expo} - {self.amount}'

    def clean(self):
        super().clean()

        # Retrieve the latest CargoByBalance for the associated CargoBy
        latest_cargo_balance = CargoByBalance.objects.filter(
            cargo_by=self.expo
        ).order_by('-id').first()

        if latest_cargo_balance:
            if self.amount > latest_cargo_balance.current_balance:
                raise ValidationError(
                    f"Payment amount {self.amount} cannot exceed the current balance {latest_cargo_balance.current_balance}.")

    def save(self, *args, **kwargs):
        if not self.pk:  # Only for new instances
            # Retrieve the latest CargoByBalance for the associated CargoBy
            latest_cargo_balance = CargoByBalance.objects.filter(
                cargo_by=self.expo
            ).order_by('-id').first()

            if latest_cargo_balance:
                # Calculate the remain amount based on the latest balance
                self.remain_amount = latest_cargo_balance.current_balance - self.amount
                self.remain_amount = max(
                    self.remain_amount, 0)  # Ensure non-negative
            else:
                # If no previous balance, remain amount equals payment amount
                self.remain_amount = self.amount

        with transaction.atomic():
            super().save(*args, **kwargs)

            # Calculate the debit and credit amounts
            amount_in = 0
            amount_out = self.amount
            current_date = date.today()

            # Retrieve the previous balance of cargo
            ca_previous_balance = CargoByBalance.objects.filter(
                cargo_by=self.expo
            ).order_by('-id').values('current_balance').first()

            ca_previous_balance = ca_previous_balance['current_balance'] if ca_previous_balance else 0

            # Calculate the current balance sender
            ca_current_balance = ca_previous_balance + (amount_in - amount_out)

            # Define existing_sender_account outside the transaction block
            existing_cargo_account = CargoByBalance.objects.filter(
                tx_number=f'P00{self.id}'
            ).first()
            # Use transaction to handle the creation logic
            with transaction.atomic():
                if amount_out > 0 and not existing_cargo_account:
                    # Create a new instance of SenderBalance
                    cargo_account = CargoByBalance(
                        tx_date=current_date,
                        cargo_by=self.expo,
                        tx_number=f'P00{self.id}',
                        description=f'account credited for {self.expo} against  receipt no: {self.id} payment!',
                        amount_in=0,
                        amount_out=amount_out,
                        previous_balance=ca_previous_balance,
                        current_balance=ca_current_balance,
                        remarks=f'account credited for {self.expo} gainst  receipt no: {self.id} payment!'
                    )
                    cargo_account.save()
                super().save(*args, **kwargs)


class ReceivePaymentFromSender(models.Model):
    sender = models.ForeignKey(Sender, on_delete=models.PROTECT)
    amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    remain_amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0, validators=[MinValueValidator(0)])
    remarks = models.CharField(max_length=255, default='N/A')
    created_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='received_payment_from_sender_created', null=True)
    updated_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='received_payment_from_sender_updated', null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f'{self.sender} - {self.amount}'

    def clean(self):
        super().clean()

        # Retrieve the latest CargoByBalance for the associated CargoBy
        latest_cargo_balance = SenderBalance.objects.filter(
            sender=self.sender
        ).order_by('-id').first()

        if latest_cargo_balance:
            if self.amount > latest_cargo_balance.current_balance:
                raise ValidationError(
                    f"Payment amount {self.amount} cannot exceed the current balance {latest_cargo_balance.current_balance}.")

    def save(self, *args, **kwargs):
        if not self.pk:  # Only for new instances
            # Retrieve the latest CargoByBalance for the associated CargoBy
            latest_cargo_balance = SenderBalance.objects.filter(
                sender=self.sender
            ).order_by('-id').first()

            if latest_cargo_balance:
                # Calculate the remain amount based on the latest balance
                self.remain_amount = latest_cargo_balance.current_balance - self.amount
                self.remain_amount = max(
                    self.remain_amount, 0)  # Ensure non-negative
            else:
                # If no previous balance, remain amount equals payment amount
                self.remain_amount = self.amount

        with transaction.atomic():
            super().save(*args, **kwargs)

            # Calculate the debit and credit amounts
            amount_in = 0
            amount_out = self.amount
            current_date = date.today()

            # Retrieve the previous balance of cargo
            ca_previous_balance = SenderBalance.objects.filter(
                sender=self.sender
            ).order_by('-id').values('current_balance').first()

            ca_previous_balance = ca_previous_balance['current_balance'] if ca_previous_balance else 0

            # Calculate the current balance sender
            ca_current_balance = ca_previous_balance + (amount_in - amount_out)

            # Define existing_sender_account outside the transaction block
            existing_cargo_account = SenderBalance.objects.filter(
                tx_number=f'P00{self.id}'
            ).first()
            # Use transaction to handle the creation logic
            with transaction.atomic():
                if amount_out > 0 and not existing_cargo_account:
                    # Create a new instance of SenderBalance
                    sender_account = SenderBalance(
                        tx_date=current_date,
                        sender=self.sender,
                        tx_number=f'P00{self.id}',
                        description=f'account credited for {self.sender} against  receipt no: {self.id} payment!',
                        amount_in=0,
                        amount_out=amount_out,
                        previous_balance=ca_previous_balance,
                        current_balance=ca_current_balance,
                        remarks=f'account credited for {self.sender} gainst  receipt no: {self.id} payment!'
                    )
                    sender_account.save()
                super().save(*args, **kwargs)


class ExpenseCategory(models.Model):
    title = models.CharField(max_length=255)
    remarks = models.TextField(blank=True, null=True)

    class Meta:
        permissions = [
            ("bulk_delete", "Can delete bulk?"),
            ("download_pdf", "Can download PDF?"),
            ("download_excel", "Can download Excel?"),
            ("bulk_status", "Can can update status?"),
        ]

    def __str__(self):
        return self.title


class AddExpense(models.Model):
    expense_category = models.ForeignKey(
        ExpenseCategory, on_delete=models.PROTECT)
    paid_by = models.CharField(
        max_length=255, default='Naqib')
    paid_to = models.CharField(max_length=255,)
    amount = models.DecimalField(
        max_digits=10, decimal_places=2, default=0)
    currency = models.ForeignKey(
        Currency, on_delete=models.PROTECT)
    description = models.TextField(
        null=True, blank=True, default='N/A')
    remarks = models.TextField(
        blank=True, null=True, default='N/A')
    date = models.DateField(null=True, blank=True)
    created_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='expense_created', null=True)
    updated_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, related_name='expense_updated', null=True)
    created_at = models.DateTimeField(
        auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        permissions = [
            ("expense_bulk_delete", "Can delete bulk?"),
            ("expense_download_pdf", "Can download PDF?"),
            ("expense_download_excel", "Can download Excel?"),
            ("expense_report", "Can see expense Report?"),
        ]

    def __str__(self):
        return f'{self.expense_category} - {self.amount}'
