from uuid import uuid4
from django.db import models, transaction
from django.contrib.auth.models import User
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from django_ledger.models import (
    VendorModel,
    EntityModel,
    EntityUnitModel,
    ItemModel,
    AccountModel,
    ItemModelAbstract,
    UnitOfMeasureModel,
    CustomerModel,
    ItemModelQuerySet,

)
from decimal import Decimal, InvalidOperation
from django.core.exceptions import ValidationError
from phonenumber_field.modelfields import PhoneNumberField
from django.contrib.contenttypes.models import ContentType
from django.utils.timezone import now
from .mixins import LocalizedNameMixin


class CarMake(models.Model, LocalizedNameMixin):
    id_car_make = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255)
    arabic_name = models.CharField(max_length=255)
    logo = models.ImageField(_('logo'), upload_to='car_make', blank=True, null=True)
    is_sa_import = models.BooleanField(default=False)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Make"


class CarModel(models.Model, LocalizedNameMixin):
    id_car_model = models.AutoField(primary_key=True)
    id_car_make = models.ForeignKey(CarMake, models.DO_NOTHING, db_column='id_car_make')
    name = models.CharField(max_length=255)
    arabic_name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Model"


class CarSerie(models.Model, LocalizedNameMixin):
    id_car_serie = models.AutoField(primary_key=True)
    id_car_model = models.ForeignKey(CarModel, models.DO_NOTHING, db_column='id_car_model')
    name = models.CharField(max_length=255)
    arabic_name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Series"


class CarTrim(models.Model, LocalizedNameMixin):
    id_car_trim = models.AutoField(primary_key=True)
    id_car_serie = models.ForeignKey(CarSerie, models.DO_NOTHING, db_column='id_car_serie')
    name = models.CharField(max_length=255)
    arabic_name = models.CharField(max_length=255)
    start_production_year = models.IntegerField(blank=True, null=True)
    end_production_year = models.IntegerField(blank=True, null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Trim"


class CarSpecification(models.Model, LocalizedNameMixin):
    id_car_specification = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255)
    arabic_name = models.CharField(max_length=255)
    id_parent = models.ForeignKey('self', models.DO_NOTHING, db_column='id_parent', blank=True, null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Specification"


class CarSpecificationValue(models.Model):
    id_car_specification_value = models.AutoField(primary_key=True)
    id_car_trim = models.ForeignKey(CarTrim, models.DO_NOTHING, db_column='id_car_trim')
    id_car_specification = models.ForeignKey(CarSpecification, models.DO_NOTHING, db_column='id_car_specification')
    value = models.CharField(max_length=500)
    unit = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return f"{self.id_car_specification.name}: {self.value} {self.unit}"

    class Meta:
        verbose_name = "Specification Value"


# Car Model
class CarStatusChoices(models.TextChoices):
    AVAILABLE = 'available', _('Available')
    SOLD = 'sold', _('Sold')
    HOLD = 'hold', _('Hold')
    DAMAGED = 'damaged', _('Damaged')
    RESERVED = 'reserved', _('Reserved')


class CarStockTypeChoices(models.TextChoices):
    NEW = 'new', _('New')
    USED = 'used', _('Used')


class Car(models.Model):
    vin = models.CharField(max_length=17, unique=True, verbose_name=_("VIN"))
    dealer = models.ForeignKey(
        "Dealer",
        models.DO_NOTHING,
        related_name='cars',
        verbose_name=_("Dealer")
    )

    vendor = models.ForeignKey(
        "Vendor",
        models.DO_NOTHING,
        null=True,
        blank=True,
        related_name='cars',
        verbose_name=_("Vendor")
    )
    id_car_make = models.ForeignKey(
        CarMake,
        models.DO_NOTHING,
        db_column='id_car_make',
        null=True,
        blank=True,
        verbose_name=_("Make")
    )
    id_car_model = models.ForeignKey(
        CarModel,
        models.DO_NOTHING,
        db_column='id_car_model',
        null=True,
        blank=True,
        verbose_name=_("Model")
    )
    year = models.IntegerField(verbose_name=_("Year"))
    id_car_serie = models.ForeignKey(
        CarSerie,
        models.DO_NOTHING,
        db_column='id_car_serie',
        null=True,
        blank=True,
        verbose_name=_("Series")
    )
    id_car_trim = models.ForeignKey(
        CarTrim,
        models.DO_NOTHING,
        db_column='id_car_trim',
        null=True,
        blank=True,
        verbose_name=_("Trim")
    )
    status = models.CharField(
        max_length=10,
        choices=CarStatusChoices,
        default=CarStatusChoices.AVAILABLE,
        verbose_name=_("Status")
    )
    stock_type = models.CharField(
        max_length=10,
        choices=CarStockTypeChoices,
        default=CarStockTypeChoices.NEW,
        verbose_name=_("Stock Type")
    )
    remarks = models.TextField(blank=True, null=True, verbose_name=_("Remarks"))
    mileage = models.IntegerField(blank=True, null=True, verbose_name=_("Mileage"))
    receiving_date = models.DateTimeField(verbose_name=_("Receiving Date"))

    class Meta:
        verbose_name = _("Car")
        verbose_name_plural = _("Cars")

    def __str__(self):
        make = self.id_car_make.name if self.id_car_make else "Unknown Make"
        model = self.id_car_model.name if self.id_car_model else "Unknown Model"
        trim = self.id_car_trim.name if self.id_car_trim else "Unknown Trim"
        return f"{self.year} - {make} - {model} - {trim}"

    def is_reserved(self):
        active_reservations = self.reservations.filter(reserved_until__gt=now())
        return active_reservations.exists()

    @property
    def selling_price(self):
        finance = self.finances.first()
        return finance.selling_price if finance else Decimal('0.00')

    @property
    def discount_amount(self):
        finance = self.finances.first()
        return finance.discount_amount if finance else Decimal('0.00')

    @property
    def vat_amount(self):
        finance = self.finances.first()
        return finance.vat_amount if finance else Decimal('0.00')

    @property
    def total(self):
        finance = self.finances.first()
        return finance.total if finance else Decimal('0.00')


class CarReservation(models.Model):
    car = models.ForeignKey('Car', on_delete=models.CASCADE, related_name='reservations')
    reserved_by = models.ForeignKey(User, on_delete=models.CASCADE)
    reserved_at = models.DateTimeField(auto_now_add=True)
    reserved_until = models.DateTimeField()

    def is_active(self):
        return self.reserved_until > now()

    class Meta:
        unique_together = ('car', 'reserved_until')
        ordering = ['-reserved_at']


# Car Finance Model
class CarFinance(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='finances')
    cost_price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Cost Price"))
    selling_price = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Selling Price"))
    profit_margin = models.DecimalField(max_digits=14,
                                        decimal_places=2,
                                        verbose_name=_("Profit Margin"),
                                        editable=False)
    vat_amount = models.DecimalField(max_digits=14,
                                        decimal_places=2,
                                        verbose_name=_("Vat Amount"),
                                        editable=False)
    discount_amount = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Discount Amount"),
                                          default=Decimal('0.00'))
    registration_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Registration Fee"),
                                           default=Decimal('0.00'))
    administration_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Administration Fee"),
                                             default=Decimal('0.00'))
    transportation_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Transportation Fee"),
                                             default=Decimal('0.00'))
    custom_card_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Custom Card Fee"),
                                          default=Decimal('0.00'))
    vat_rate = models.DecimalField(max_digits=14, decimal_places=2, default=Decimal('0.15'), verbose_name=_("VAT Rate"),)
    total = models.DecimalField(max_digits=14, decimal_places=2, default=Decimal('0.00'), null=True, blank=True)

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

    def save(self, *args, **kwargs):
        self.full_clean()
        try:
            services = self.administration_fee + self.transportation_fee + self.custom_card_fee
            price_after_discount = self.selling_price - self.discount_amount
            total_vat_amount = (price_after_discount + services) * self.vat_rate
            self.vat_amount = self.selling_price * self.vat_rate
            self.profit_margin = self.selling_price - self.cost_price - self.discount_amount - self.registration_fee
            self.total = price_after_discount + services + total_vat_amount + self.registration_fee

        except InvalidOperation as e:
            raise ValidationError(_("Invalid decimal operation: %s") % str(e))

        super().save(*args, **kwargs)

    class Meta:
        verbose_name = _("Car Financial Details")

    @property
    def total_vat_amount(self):
        services = self.administration_fee + self.transportation_fee + self.custom_card_fee
        price_after_discount = self.selling_price - self.discount_amount
        return (price_after_discount + services) * self.vat_rate


class ExteriorColors(models.Model, LocalizedNameMixin):
    name = models.CharField(max_length=255, verbose_name=_("Name"))
    arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
    rgb = models.CharField(max_length=24, blank=True, null=True, verbose_name=_("RGB"))

    class Meta:
        verbose_name = _("Exterior Colors")
        verbose_name_plural = _("Exterior Colors")

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


class InteriorColors(models.Model, LocalizedNameMixin):
    name = models.CharField(max_length=255, verbose_name=_("Name"))
    arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
    rgb = models.CharField(max_length=24, blank=True, null=True, verbose_name=_("RGB"))

    class Meta:
        verbose_name = _("Interior Colors")
        verbose_name_plural = _("Interior Colors")

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


# Colors Model
class CarColors(models.Model):
    car = models.ForeignKey('Car', on_delete=models.CASCADE, related_name='colors')
    exterior = models.ForeignKey('ExteriorColors', on_delete=models.CASCADE, related_name='colors')
    interior = models.ForeignKey('InteriorColors', on_delete=models.CASCADE, related_name='colors')

    class Meta:
        verbose_name = _("Color")
        verbose_name_plural = _("Colors")
        unique_together = ('car', 'exterior', 'interior')

    def __str__(self):
        return f"{self.car} ({self.exterior.name}) ({self.interior.name})"


# Custom Card Model
class CustomCard(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='custom_cards', verbose_name=_("Car"))
    custom_number = models.CharField(max_length=255, verbose_name=_("Custom Number"))
    custom_date = models.DateField(verbose_name=_("Custom Date"))

    class Meta:
        verbose_name = _("Custom Card")
        verbose_name_plural = _("Custom Cards")

    def __str__(self):
        return f"{self.car} - {self.custom_number}"


# Car Registration Model
class CarRegistration(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='registrations', verbose_name=_("Car"))
    plate_number = models.IntegerField(verbose_name=_("Plate Number"))
    text1 = models.CharField(max_length=1, verbose_name=_("Text 1"))
    text2 = models.CharField(max_length=1, verbose_name=_("Text 2"))
    text3 = models.CharField(max_length=1, verbose_name=_("Text 3"))
    registration_date = models.DateTimeField(verbose_name=_("Registration Date"))

    class Meta:
        verbose_name = _("Registration")
        verbose_name_plural = _("Registrations")

    def __str__(self):
        return f"{self.plate_number} - {self.text1} {self.text2} {self.text3}"


# TimestampedModel Abstract Class
class TimestampedModel(models.Model):
    created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
    updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))

    class Meta:
        abstract = True


# Dealer Model
class Dealer(models.Model, LocalizedNameMixin):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='dealer')
    crn = models.CharField(max_length=10, verbose_name=_("Commercial Registration Number"))
    vrn = models.CharField(max_length=15, verbose_name=_("VAT Registration Number"))
    arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
    name = models.CharField(max_length=255, verbose_name=_("English Name"))
    phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
    address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
    logo = models.ImageField(upload_to="logos/users", blank=True, null=True, verbose_name=_("Logo"))

    class Meta:
        verbose_name = _("Dealer")
        verbose_name_plural = _("Dealers")

    def __str__(self):
        return self.name


# Vendor Model
class Vendor(models.Model, LocalizedNameMixin):
    dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='vendors')
    crn = models.CharField(max_length=10, unique=True, verbose_name=_("Commercial Registration Number"))
    vrn = models.CharField(max_length=15, unique=True, verbose_name=_("VAT Registration Number"))
    arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
    name = models.CharField(max_length=255, verbose_name=_("English Name"))
    contact_person = models.CharField(max_length=100, verbose_name=_("Contact Person"))
    phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
    address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
    logo = models.ImageField(upload_to="logos/vendors", blank=True, null=True, verbose_name=_("Logo"))

    class Meta:
        verbose_name = _("Vendor")
        verbose_name_plural = _("Vendors")

    def __str__(self):
        return self.name


# Customer Model
class Customer(models.Model):
    dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='customers')
    first_name = models.CharField(max_length=50, verbose_name=_("First Name"))
    middle_name = models.CharField(max_length=50, blank=True, null=True, verbose_name=_("Middle Name"))
    last_name = models.CharField(max_length=50, verbose_name=_("Last Name"))
    email = models.EmailField(unique=True, verbose_name=_("Email"))
    national_id = models.CharField(max_length=10, unique=True, verbose_name=_("National ID"))
    phone_number = PhoneNumberField(region='SA', unique=True, verbose_name=_("Phone Number"))
    address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
    created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))

    class Meta:
        verbose_name = _("Customer")
        verbose_name_plural = _("Customers")

    def __str__(self):
        middle = f" {self.middle_name}" if self.middle_name else ''
        return f"{self.first_name}{middle} {self.last_name}"

    @property
    def get_full_name(self):
        return f"{self.first_name} {self.middle_name} {self.last_name}"


class SaleQuotation(models.Model):
    STATUS_CHOICES = [
        ("DRAFT", _("Draft")),
        ("CONFIRMED", _("Confirmed")),
        ("CANCELED", _("Canceled")),
    ]
    dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='sales', null=True)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="quotations", verbose_name=_("Customer"))
    amount = models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=10, verbose_name=_("Amount"))
    remarks = models.TextField(blank=True, null=True, verbose_name=_("Remarks"))
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default="DRAFT", verbose_name=_("Status"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))

    def confirm(self):
        """Confirm the quotation and lock financial details."""
        if self.status != "DRAFT":
            raise ValueError(_("Only draft quotations can be confirmed."))
        self.status = "CONFIRMED"
        self.save()

    def cancel(self):
        """Cancel the quotation."""
        if self.status == "CONFIRMED":
            raise ValueError(_("Cannot cancel a confirmed quotation."))
        self.status = "CANCELED"
        self.save()

    def __str__(self):
        return f"Quotation #{self.id} for {self.customer}"


class SaleQuotationCar(models.Model):
    quotation = models.ForeignKey(
        SaleQuotation,
        on_delete=models.CASCADE,
        related_name="quotation_cars",
        verbose_name=_("Quotation")
    )
    car = models.ForeignKey(
        Car,
        on_delete=models.CASCADE,
        verbose_name=_("Car")
    )
    # dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="sale_cars", verbose_name=_("Dealer"))
    quantity = models.PositiveIntegerField(default=1, verbose_name=_("Quantity"))
    # price = models.DecimalField(decimal_places=2, max_digits=10, verbose_name=_("Price"), editable=False)



    def get_financial_details(self):
        """Retrieve financial details dynamically from CarFinance."""
        car_finance = self.car.finances.first()
        if not car_finance:
            return None

        return {
            "selling_price": car_finance.selling_price,
            "administration_fee": car_finance.administration_fee,
            "transportation_fee": car_finance.transportation_fee,
            "custom_card_fee": car_finance.custom_card_fee,
            "registration_fee": car_finance.registration_fee,
            "vat_rate": car_finance.vat_rate,
            "discount_amount": car_finance.discount_amount,
            "total_amount": car_finance.total,
        }

    def __str__(self):
        return f"{self.car} - Quotation #{self.quotation.id}"


class SalesOrder(models.Model):
    quotation = models.OneToOneField(SaleQuotation, on_delete=models.CASCADE, related_name="sales_order", verbose_name=_("Quotation"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
    total_amount = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Total Amount"))

    def __str__(self):
        return f"Sales Order #{self.id} from Quotation #{self.quotation.id}"


