
from django.db import models
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db.models import Sum

User = settings.AUTH_USER_MODEL


# ================= BUILDING =================
class Building(models.Model):
    name = models.CharField(max_length=255)
    location = models.CharField(max_length=255)

    landlord = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='buildings'
    )

    caretaker = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='managed_buildings'
    )

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return self.name


#=============UNIT================

from django.db import models
from django.core.exceptions import ValidationError
from django.db.models import Sum
from accounts.models import User


# ================= UNIT =================
from django.db import models
from django.core.exceptions import ValidationError
from django.db.models import Sum
from accounts.models import User


# ================= UNIT =================
class Unit(models.Model):

    UNIT_TYPE_CHOICES = (
        ("bedsitter", "Bedsitter"),
        ("1br", "1 Bedroom"),
        ("2br", "2 Bedroom"),
        ("3br", "3 Bedroom"),
    )

    building = models.ForeignKey(
        "properties.Building",
        on_delete=models.CASCADE,
        related_name='units'
    )

    unit_number = models.CharField(max_length=50)
    unit_type = models.CharField(max_length=20, choices=UNIT_TYPE_CHOICES)

    rent_amount = models.DecimalField(max_digits=10, decimal_places=2)
    deposit = models.DecimalField(max_digits=10, decimal_places=2)

    max_occupants = models.PositiveIntegerField(default=1)

    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        related_name='created_units'
    )

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
        unique_together = ('building', 'unit_number')

    def __str__(self):
        return f"{self.building.name} - {self.unit_number}"

    def clean(self):
        if self.max_occupants < 1:
            raise ValidationError("Unit must allow at least 1 occupant")

    # ================= OCCUPANCY =================

    @property
    def current_occupancy(self):
        """
        Count ONLY active tenants from history
        """
        return self.tenant_history.filter(is_current=True).count()

    def is_full(self):
        return self.current_occupancy >= self.max_occupants

    @property
    def is_occupied(self):
        return self.tenant_history.filter(is_current=True).exists()

    def occupancy_status(self):
        if self.is_full():
            return "Full"
        elif self.current_occupancy > 0:
            return "Partially Occupied"
        return "Vacant"

    # ================= FINANCIALS (FIXED SOURCE OF TRUTH) =================

    def total_rent_expected(self):
        """
        Total billed invoices (rent + deposit where applicable)
        """
        return self.invoices.filter(amount__gt=0).aggregate(
            total=Sum('amount')
        )['total'] or 0

    def total_collected(self):
        """
        Total payments received
        """
        return self.payments.aggregate(
            total=Sum('amount')
        )['total'] or 0

    def total_balance(self):
        """
        Outstanding balance
        """
        return self.total_rent_expected() - self.total_collected()

    def financial_status(self):
        balance = self.total_balance()

        if balance <= 0:
            return "Cleared"
        elif self.total_collected() > 0:
            return "Partial"
        return "Unpaid"
    
    
# ================= UNIT TENANT HISTORY =================
class UnitTenantHistory(models.Model):
    unit = models.ForeignKey(
        Unit,
        on_delete=models.CASCADE,
        related_name="tenant_history"
    )

    tenant = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True
    )

    start_date = models.DateTimeField(auto_now_add=True)
    end_date = models.DateTimeField(null=True, blank=True)

    is_current = models.BooleanField(default=True)

    class Meta:
        ordering = ['-start_date']

    def __str__(self):
        return f"{self.unit} - {self.tenant}"

    def end_tenancy(self):
        from django.utils import timezone
        self.end_date = timezone.now()
        self.is_current = False
        self.save()

    # ✅ ENFORCE SINGLE ACTIVE TENANCY
    def save(self, *args, **kwargs):
        if self.is_current:
            UnitTenantHistory.objects.filter(
                unit=self.unit,
                tenant=self.tenant,
                is_current=True
            ).update(is_current=False)
        super().save(*args, **kwargs)


# ================= RENT HISTORY =================
class UnitRentHistory(models.Model):
    unit = models.ForeignKey(
        Unit,
        on_delete=models.CASCADE,
        related_name="rent_history"
    )

    old_rent = models.DecimalField(max_digits=10, decimal_places=2)
    new_rent = models.DecimalField(max_digits=10, decimal_places=2)

    changed_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-changed_at']

    def __str__(self):
        return f"{self.unit} rent changed from {self.old_rent} to {self.new_rent}"


# ================= INSPECTION =================
class UnitInspection(models.Model):
    unit = models.ForeignKey(Unit, on_delete=models.CASCADE, related_name="inspections")
    tenant = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    notes = models.TextField(blank=True)
    image = models.ImageField(upload_to="inspections/", null=True, blank=True)

    inspected_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name="inspections_done"
    )

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.unit} - {self.tenant}"


# ================= TENANT EXIT =================
class TenantExit(models.Model):

    EXIT_TYPE_CHOICES = (
        ("vacate", "Vacate"),
        ("eviction", "Eviction"),
    )

    tenant = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    unit = models.ForeignKey(Unit, on_delete=models.CASCADE)

    exit_type = models.CharField(max_length=20, choices=EXIT_TYPE_CHOICES)

    reason = models.CharField(max_length=255, blank=True)
    notes = models.TextField(blank=True)

    inspection_notes = models.TextField(blank=True)
    inspection_image = models.ImageField(upload_to="exit_inspections/", null=True, blank=True)

    initiated_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name="exits_initiated"
    )

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.tenant} - {self.exit_type}"