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 phonenumber_field.modelfields import PhoneNumberField
from django.contrib.contenttypes.models import ContentType
from decimal import Decimal
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")


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.choices,
        default=CarStatusChoices.AVAILABLE,
        verbose_name=_("Status"),
    )
    stock_type = models.CharField(
        max_length=10,
        choices=CarStockTypeChoices.choices,
        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 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")
    )
    profit_margin = models.DecimalField(
        max_digits=10, decimal_places=2, verbose_name=_("Profit Margin")
    )
    selling_price = models.DecimalField(
        max_digits=14, decimal_places=2, verbose_name=_("Selling Price"), editable=False
    )
    vat_rate = models.DecimalField(
        max_digits=10, decimal_places=2, default=0.15, verbose_name=_("VAT Rate")
    )
    vat_amount = models.DecimalField(
        max_digits=12, decimal_places=2, verbose_name=_("VAT Amount"), editable=False
    )
    total = models.DecimalField(
        max_digits=14, decimal_places=2, verbose_name=_("Total Amount"), editable=False
    )

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

    def save(self, *args, **kwargs):
        self.full_clean()
        self.selling_price = self.cost_price * (1 + self.profit_margin)
        self.vat_amount = self.selling_price * self.vat_rate
        self.total = self.selling_price + self.vat_amount
        super().save(*args, **kwargs)

    def __str__(self):
        return (
            f"Car Financial Details for {self.car}: Selling Price {self.selling_price}"
        )


# Colors Model
class CarColors(models.Model):
    class ColorType(models.TextChoices):
        EXTERIOR = "exterior", _("Exterior")
        INTERIOR = "interior", _("Interior")

    car = models.ForeignKey("Car", on_delete=models.CASCADE, related_name="colors")
    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"))
    color_type = models.CharField(
        max_length=10,
        choices=ColorType.choices,
        default=ColorType.EXTERIOR,
        verbose_name=_("Color Type"),
    )

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

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


# 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")
    )

    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}"

# Create Entity
@receiver(post_save, sender=Dealer)
def create_ledger_entity(sender, instance, created, **kwargs):
    if created:
        entity = EntityModel.objects.create(
            name=instance.name,
            admin=instance.user,
            address_1=instance.address,
            fy_start_month=1,
            accrual_method=True,
            depth=0,
        )

        default_coa = entity.create_chart_of_accounts(assign_as_default=True,
                                                      commit=True,
                                                      coa_name=_("Chart of Accounts"))
        if default_coa:
            entity.populate_default_coa(activate_accounts=True, coa_model=default_coa)
        print(f"Ledger entity created for Dealer: {instance.name}")


# # Create Vendor
@receiver(post_save, sender=Vendor)
def create_ledger_vendor(sender, instance, created, **kwargs):

    if created:
        entity = EntityModel.objects.filter(name=instance.dealer.name).first()

        vendor = VendorModel.objects.update_or_create(
            entity_model=entity,
            vendor_name=instance.name,
            vendor_number=instance.crn,
            address_1=instance.address,
            phone=instance.phone_number,
            tax_id_number=instance.vrn,
            active=True,
            hidden=False,
            additional_info={
                "arabic_name": instance.arabic_name,
                "contact_person": instance.contact_person,
            },
        )

        print(f"VendorModel created for Vendor: {instance.name}")


@receiver(post_save, sender=Customer)
def create_customer(sender, instance, created, **kwargs):

    if created:
        entity = EntityModel.objects.filter(name=instance.dealer.name).first()
        name = f"{instance.first_name} {instance.middle_name} {instance.last_name}"

        customer = CustomerModel.objects.create(
            entity_model=entity,
            customer_name=name,
            customer_number=instance.national_id,
            address_1=instance.address,
            phone=instance.phone_number,
            email=instance.email,
            sales_tax_rate=0.15,
        )

        print(f"Customer created: {name}")


# # Create Item
# @receiver(post_save, sender=Car)
# def create_item_model(sender, instance, created, **kwargs):
#     item_name = f"{instance.year} - {instance.id_car_make} - {instance.id_car_model} - {instance.id_car_trim}"
#     uom_name = _("Car")
#     unit_abbr = _("C")
#
#     uom, uom_created = UnitOfMeasureModel.objects.get_or_create(
#         name=uom_name,
#         unit_abbr=unit_abbr
#     )
#
#     if uom_created:
#         print(f"UOM created: {uom_name}")
#     else:
#         print(f"Using existing UOM: {uom_name}")
#
#     entity = EntityModel.objects.filter(name=instance.dealer.name).first()
#
#     inventory_account = AccountModel.objects.first()
#     cogs_account = AccountModel.objects.first()
#     earnings_account = AccountModel.objects.first()
#
#     item = ItemModel.objects.create(
#         entity=entity,
#         uom=uom,
#         name=item_name,
#         item_role=ItemModelAbstract.ITEM_ROLE_INVENTORY,
#         item_type=ItemModelAbstract.ITEM_TYPE_MATERIAL,
#         item_id=instance.vin,
#         sold_as_unit=True,
#         inventory_received=1.00,
#         inventory_received_value=0.00,
#         inventory_account=inventory_account,
#         for_inventory=True,
#         is_product_or_service=True,
#         cogs_account=cogs_account,
#         earnings_account=earnings_account,
#         is_active=True,
#         additional_info={
#             "remarks": instance.remarks,
#             "status": instance.status,
#             "stock_type": instance.stock_type,
#             "mileage": instance.mileage,
#         },
#     )
#
#     print(f"ItemModel {'created' if created else 'updated'} for Car: {item.name}")
#
#
# # update price - CarFinance
# @receiver(post_save, sender=CarFinance)
# def update_item_model_cost(sender, instance, created, **kwargs):
#
#     ItemModel.objects.filter(item_id=instance.car.vin).update(
#         inventory_received_value=instance.cost_price,
#         default_amount=instance.cost_price,
#     )
#     print(f"Inventory item updated with CarFinance data for Car: {instance.car}")
