"""
Analytics models for Dubai Land Department data.
"""
from django.db import models
from django.contrib.postgres.indexes import BTreeIndex
# JSONField is now in django.db.models in Django 3.1+
from apps.core.models import TimeStampedModel
import uuid


class Broker(TimeStampedModel):
    """Real estate brokers data."""
    broker_number = models.CharField(max_length=20, unique=True, db_index=True)
    broker_name_en = models.CharField(max_length=255)
    gender = models.CharField(max_length=10, choices=[
        ('male', 'Male'),
        ('female', 'Female'),
        ('أنثى', 'Female (Arabic)'),
    ])
    license_start_date = models.DateTimeField()
    license_end_date = models.DateTimeField()
    webpage = models.URLField(blank=True, null=True)
    phone = models.CharField(max_length=50, blank=True)
    fax = models.CharField(max_length=50, blank=True)
    real_estate_number = models.CharField(max_length=20, blank=True)
    real_estate_name_en = models.CharField(max_length=255, blank=True)

    class Meta:
        db_table = 'brokers'
        indexes = [
            BTreeIndex(fields=['broker_number']),
            BTreeIndex(fields=['real_estate_name_en']),
            BTreeIndex(fields=['license_end_date']),
        ]

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


class Developer(TimeStampedModel):
    """Real estate developers data."""
    developer_number = models.CharField(max_length=20, unique=True, db_index=True)
    developer_name_en = models.CharField(max_length=255)

    class Meta:
        db_table = 'developers'

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


class Project(TimeStampedModel):
    """Real estate projects data."""
    project_number = models.CharField(max_length=20, unique=True, db_index=True)
    project_name_en = models.CharField(max_length=255)
    developer = models.ForeignKey(Developer, on_delete=models.CASCADE, related_name='projects')
    start_date = models.DateTimeField()
    end_date = models.DateTimeField(null=True, blank=True)
    adoption_date = models.DateTimeField(null=True, blank=True)
    project_type = models.CharField(max_length=50, choices=[
        ('Normal', 'Normal'),
        ('Escrow', 'Escrow'),
    ])
    project_value = models.DecimalField(max_digits=15, decimal_places=2, null=True, blank=True)
    escrow_account_number = models.CharField(max_length=50, blank=True)
    project_status = models.CharField(max_length=20, choices=[
        ('ACTIVE', 'Active'),
        ('PENDING', 'Pending'),
        ('CANCELLED', 'Cancelled'),
        ('COMPLETED', 'Completed'),
    ])
    percent_completed = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    inspection_date = models.DateTimeField(null=True, blank=True)
    completion_date = models.DateTimeField(null=True, blank=True)
    description_en = models.TextField(blank=True)
    area_en = models.CharField(max_length=100)
    zone_en = models.CharField(max_length=100)
    count_land = models.IntegerField(default=0)
    count_building = models.IntegerField(default=0)
    count_villa = models.IntegerField(default=0)
    count_unit = models.IntegerField(default=0)
    master_project_en = models.CharField(max_length=255, blank=True)

    class Meta:
        db_table = 'projects'
        indexes = [
            BTreeIndex(fields=['project_number']),
            BTreeIndex(fields=['project_status']),
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['zone_en']),
            BTreeIndex(fields=['developer']),
        ]

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


class Land(TimeStampedModel):
    """Land data."""
    land_type = models.CharField(max_length=50, choices=[
        ('Agricultural', 'Agricultural'),
        ('Commercial', 'Commercial'),
        ('Residential', 'Residential'),
        ('Industrial', 'Industrial'),
    ])
    property_sub_type = models.CharField(max_length=50)
    actual_area = models.DecimalField(max_digits=10, decimal_places=2)
    is_offplan = models.CharField(max_length=10, choices=[
        ('Ready', 'Ready'),
        ('Off-Plan', 'Off-Plan'),
    ])
    pre_registration_number = models.CharField(max_length=50, blank=True)
    is_freehold = models.CharField(max_length=20, choices=[
        ('Free Hold', 'Free Hold'),
        ('Non Free Hold', 'Non Free Hold'),
    ])
    dm_zip_code = models.CharField(max_length=10, blank=True)
    master_project = models.CharField(max_length=255, blank=True)
    project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='lands')
    area_en = models.CharField(max_length=100)
    zone_en = models.CharField(max_length=100)

    class Meta:
        db_table = 'lands'
        indexes = [
            BTreeIndex(fields=['land_type']),
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['zone_en']),
            BTreeIndex(fields=['is_freehold']),
            BTreeIndex(fields=['actual_area']),
        ]

    def __str__(self):
        return f"{self.area_en} - {self.land_type} ({self.actual_area} sqft)"


class Transaction(TimeStampedModel):
    """Real estate transactions data."""
    transaction_number = models.CharField(max_length=50, unique=True, db_index=True)
    instance_date = models.DateTimeField()
    group = models.CharField(max_length=50, choices=[
        ('Mortgage', 'Mortgage'),
        ('Sale', 'Sale'),
        ('Rent', 'Rent'),
        ('Other', 'Other'),
    ])
    procedure = models.CharField(max_length=100)
    is_offplan = models.CharField(max_length=10, choices=[
        ('Off-Plan', 'Off-Plan'),
        ('Ready', 'Ready'),
    ])
    is_freehold = models.CharField(max_length=20, choices=[
        ('Free Hold', 'Free Hold'),
        ('Non Free Hold', 'Non Free Hold'),
    ])
    usage = models.CharField(max_length=50, choices=[
        ('Residential', 'Residential'),
        ('Commercial', 'Commercial'),
        ('Industrial', 'Industrial'),
        ('Mixed', 'Mixed'),
    ])
    area_en = models.CharField(max_length=100)
    property_type = models.CharField(max_length=50, choices=[
        ('Unit', 'Unit'),
        ('Villa', 'Villa'),
        ('Land', 'Land'),
        ('Building', 'Building'),
    ])
    property_sub_type = models.CharField(max_length=50)
    transaction_value = models.DecimalField(max_digits=15, decimal_places=2)
    procedure_area = models.DecimalField(max_digits=10, decimal_places=2)
    actual_area = models.DecimalField(max_digits=10, decimal_places=2)
    rooms = models.CharField(max_length=20, blank=True)
    parking = models.CharField(max_length=20, blank=True)
    nearest_metro = models.CharField(max_length=100, blank=True)
    nearest_mall = models.CharField(max_length=100, blank=True)
    nearest_landmark = models.CharField(max_length=100, blank=True)
    total_buyer = models.IntegerField(default=0)
    total_seller = models.IntegerField(default=0)
    master_project = models.CharField(max_length=255, blank=True)
    project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='transactions')

    class Meta:
        db_table = 'transactions'
        indexes = [
            BTreeIndex(fields=['transaction_number']),
            BTreeIndex(fields=['instance_date']),
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['property_type']),
            BTreeIndex(fields=['transaction_value']),
            BTreeIndex(fields=['group']),
            BTreeIndex(fields=['usage']),
        ]

    def __str__(self):
        return f"{self.transaction_number} - {self.area_en} - {self.transaction_value}"

    @property
    def price_per_sqft(self):
        """Calculate price per square foot."""
        if self.actual_area and self.actual_area > 0:
            return self.transaction_value / self.actual_area
        return None


class Valuation(TimeStampedModel):
    """Property valuations data."""
    property_total_value = models.DecimalField(max_digits=15, decimal_places=2)
    area_en = models.CharField(max_length=100)
    actual_area = models.DecimalField(max_digits=10, decimal_places=2)
    procedure_year = models.IntegerField()
    procedure_number = models.CharField(max_length=20)
    instance_date = models.DateTimeField()
    actual_worth = models.DecimalField(max_digits=15, decimal_places=2)
    procedure_area = models.DecimalField(max_digits=10, decimal_places=2)
    property_type = models.CharField(max_length=50, choices=[
        ('Unit', 'Unit'),
        ('Villa', 'Villa'),
        ('Land', 'Land'),
        ('Building', 'Building'),
    ])
    property_sub_type = models.CharField(max_length=50)

    class Meta:
        db_table = 'valuations'
        indexes = [
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['property_type']),
            BTreeIndex(fields=['procedure_year']),
            BTreeIndex(fields=['instance_date']),
            BTreeIndex(fields=['property_total_value']),
        ]

    def __str__(self):
        return f"{self.area_en} - {self.property_type} - {self.property_total_value}"


class Rent(TimeStampedModel):
    """Rental data."""
    registration_date = models.DateTimeField()
    start_date = models.DateTimeField()
    end_date = models.DateTimeField()
    version = models.CharField(max_length=20, choices=[
        ('New', 'New'),
        ('Renewed', 'Renewed'),
    ])
    area_en = models.CharField(max_length=100)
    contract_amount = models.DecimalField(max_digits=15, decimal_places=2)
    annual_amount = models.DecimalField(max_digits=15, decimal_places=2)
    is_freehold = models.CharField(max_length=20, choices=[
        ('Free Hold', 'Free Hold'),
        ('Non Free Hold', 'Non Free Hold'),
    ])
    actual_area = models.DecimalField(max_digits=10, decimal_places=2)
    property_type = models.CharField(max_length=50, choices=[
        ('Unit', 'Unit'),
        ('Villa', 'Villa'),
        ('Land', 'Land'),
        ('Building', 'Building'),
    ])
    property_sub_type = models.CharField(max_length=50)
    rooms = models.CharField(max_length=20, blank=True)
    usage = models.CharField(max_length=50, choices=[
        ('Residential', 'Residential'),
        ('Commercial', 'Commercial'),
        ('Industrial', 'Industrial'),
        ('Mixed', 'Mixed'),
    ])
    nearest_metro = models.CharField(max_length=100, blank=True)
    nearest_mall = models.CharField(max_length=100, blank=True)
    nearest_landmark = models.CharField(max_length=100, blank=True)
    parking = models.CharField(max_length=20, blank=True)
    total_properties = models.IntegerField(default=1)
    master_project = models.CharField(max_length=255, blank=True)
    project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='rents')

    class Meta:
        db_table = 'rents'
        indexes = [
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['property_type']),
            BTreeIndex(fields=['registration_date']),
            BTreeIndex(fields=['start_date']),
            BTreeIndex(fields=['end_date']),
            BTreeIndex(fields=['contract_amount']),
            BTreeIndex(fields=['annual_amount']),
        ]

    def __str__(self):
        return f"{self.area_en} - {self.property_type} - {self.annual_amount}"

    @property
    def rent_per_sqft(self):
        """Calculate rent per square foot."""
        if self.actual_area and self.actual_area > 0:
            return self.annual_amount / self.actual_area
        return None


class Forecast(TimeStampedModel):
    """Property price forecasts."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    area_en = models.CharField(max_length=100)
    property_type = models.CharField(max_length=50)
    property_sub_type = models.CharField(max_length=50, blank=True)
    forecast_date = models.DateTimeField()
    predicted_price = models.DecimalField(max_digits=15, decimal_places=2)
    confidence_interval_lower = models.DecimalField(max_digits=15, decimal_places=2)
    confidence_interval_upper = models.DecimalField(max_digits=15, decimal_places=2)
    model_version = models.CharField(max_length=20, default='1.0')
    accuracy_score = models.DecimalField(max_digits=5, decimal_places=4, null=True, blank=True)
    metadata = models.JSONField(default=dict)

    class Meta:
        db_table = 'forecasts'
        indexes = [
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['property_type']),
            BTreeIndex(fields=['forecast_date']),
            BTreeIndex(fields=['predicted_price']),
        ]

    def __str__(self):
        return f"{self.area_en} - {self.property_type} - {self.forecast_date}"


class MarketTrend(TimeStampedModel):
    """Market trend analysis data."""
    area_en = models.CharField(max_length=100)
    property_type = models.CharField(max_length=50)
    period_start = models.DateTimeField()
    period_end = models.DateTimeField()
    average_price = models.DecimalField(max_digits=15, decimal_places=2)
    median_price = models.DecimalField(max_digits=15, decimal_places=2)
    price_change_percent = models.DecimalField(max_digits=5, decimal_places=2)
    transaction_count = models.IntegerField()
    volume = models.DecimalField(max_digits=15, decimal_places=2)
    price_per_sqft = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)

    class Meta:
        db_table = 'market_trends'
        indexes = [
            BTreeIndex(fields=['area_en']),
            BTreeIndex(fields=['property_type']),
            BTreeIndex(fields=['period_start']),
            BTreeIndex(fields=['period_end']),
        ]

    def __str__(self):
        return f"{self.area_en} - {self.property_type} - {self.period_start} to {self.period_end}"

