from django.conf import settings
from django.db import models

from apps.core.models import Currency, TimeStampedModel


class UnitStatus(models.TextChoices):
    AVAILABLE = "available", "Available"
    RESERVED = "reserved", "Reserved"
    BOOKED = "booked", "Booked"
    CONTRACTED = "contracted", "Contracted"
    SOLD = "sold", "Sold"


class SaleStage(models.TextChoices):
    BOOKING = "booking", "Booking"
    CONTRACTED = "contracted", "Contracted sale"
    COLLECTED = "collected", "Collected revenue"
    RECOGNIZED = "recognized", "Recognized revenue"


class Customer(TimeStampedModel):
    name = models.CharField(max_length=180)
    email = models.EmailField(blank=True)
    phone = models.CharField(max_length=40, blank=True)
    country = models.CharField(max_length=120, blank=True)
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ["name"]

    def __str__(self):
        return self.name


class PropertyUnit(TimeStampedModel):
    project = models.ForeignKey("projects.Project", on_delete=models.CASCADE, related_name="property_units")
    unit_code = models.CharField(max_length=40)
    unit_type = models.CharField(max_length=80, blank=True)
    floor = models.CharField(max_length=40, blank=True)
    area = models.CharField(max_length=40, blank=True)
    list_price = models.DecimalField(max_digits=16, decimal_places=2, default=0)
    currency = models.CharField(max_length=8, choices=Currency.choices, default=Currency.BDT)
    status = models.CharField(max_length=16, choices=UnitStatus.choices, default=UnitStatus.AVAILABLE)

    class Meta:
        ordering = ["unit_code"]
        unique_together = ("project", "unit_code")

    def __str__(self):
        return f"{self.project.name} · {self.unit_code}"


class ProjectSale(TimeStampedModel):
    project = models.ForeignKey("projects.Project", on_delete=models.PROTECT, related_name="sales")
    unit = models.ForeignKey(PropertyUnit, on_delete=models.PROTECT, related_name="sales")
    customer = models.ForeignKey(Customer, on_delete=models.PROTECT, related_name="sales")
    stage = models.CharField(max_length=16, choices=SaleStage.choices, default=SaleStage.BOOKING)
    contracted_amount = models.DecimalField(max_digits=16, decimal_places=2, default=0)
    collected_amount = models.DecimalField(max_digits=16, decimal_places=2, default=0)
    currency = models.CharField(max_length=8, choices=Currency.choices, default=Currency.BDT)
    booked_at = models.DateTimeField(null=True, blank=True)
    contracted_at = models.DateTimeField(null=True, blank=True)
    collected_at = models.DateTimeField(null=True, blank=True)
    recognized_at = models.DateTimeField(null=True, blank=True)
    notes = models.TextField(blank=True)
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="created_sales",
    )

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.unit.unit_code} · {self.customer.name}"


class PropertyPayment(TimeStampedModel):
    sale = models.ForeignKey(ProjectSale, on_delete=models.CASCADE, related_name="payments")
    amount = models.DecimalField(max_digits=16, decimal_places=2)
    currency = models.CharField(max_length=8, choices=Currency.choices, default=Currency.BDT)
    occurred_on = models.DateField()
    reference = models.CharField(max_length=80, blank=True)
    notes = models.CharField(max_length=255, blank=True)
    posted_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="posted_property_payments",
    )

    class Meta:
        ordering = ["-occurred_on", "-id"]
