from django.db import models
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator  
from decimal import Decimal
from django.db.models import Sum
from django.db.models.functions import Coalesce
from django.db.models import DecimalField, Value
class Institute(models.Model):
    name = models.CharField(max_length=100)
    
    def __str__(self):
        return self.name

class Client(models.Model):
    name = models.CharField(max_length=100)
    address = models.TextField()
    institute = models.ForeignKey(Institute, on_delete=models.CASCADE)
    
    def __str__(self):
        return f"{self.name} ({self.institute.name})"

class MonthlySheet(models.Model):
    """Represents one monthly page"""
    year = models.IntegerField()
    month = models.IntegerField()  # 1-12
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        unique_together = ['year', 'month']
        ordering = ['year', 'month']
    
    def __str__(self):
        return f"{self.year}-{self.month:02d}"

class Cell(models.Model):
    """A single cell in the spreadsheet"""
    sheet = models.ForeignKey(MonthlySheet, on_delete=models.CASCADE, related_name='cells')
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    table_type = models.CharField(max_length=20, choices=[
        ('top_left', 'Top Left Table'),
        ('top_right', 'Top Right Table'),
        ('bottom_1', 'Bottom Table 1'),
        ('bottom_2', 'Bottom Table 2'),
        ('bottom_3', 'Bottom Table 3'),
    ])
    row_index = models.IntegerField()  # 0-23 for top tables, 0-9 for bottom
    column_index = models.IntegerField()  # Actually client index (0-5)
    is_formula = models.BooleanField(default=False)
    # Cell content
    value = models.DecimalField(max_digits=15, decimal_places=6, null=True, blank=True)
    formula = models.TextField(blank=True)
    
    
    # Metadata
    data_type = models.CharField(max_length=20, default='number', choices=[
        ('number', 'Number'),
        ('text', 'Text'),
        ('date', 'Date'),
    ])
    
    class Meta:
        unique_together = ['sheet', 'client', 'table_type', 'row_index', 'column_index']
        indexes = [
            models.Index(fields=['sheet', 'table_type', 'row_index']),
        ]
    
    def __str__(self):
        return f"{self.sheet} - {self.client.name} - {self.table_type}[{self.row_index}][{self.column_index}]"

class CellReference(models.Model):
    """Track dependencies between cells for calculations"""
    source_cell = models.ForeignKey(Cell, on_delete=models.CASCADE, related_name='dependents')
    target_cell = models.ForeignKey(Cell, on_delete=models.CASCADE, related_name='dependencies')
    
    class Meta:
        unique_together = ['source_cell', 'target_cell']



class Betriebskosten(models.Model):
    KOSTENTYP_CHOICES = [
        ('sach', 'Sach'),
        ('helium', 'Helium'),
    ]
    gegenstand = models.CharField("Gegenstand", max_length=200)
    buchungsdatum = models.DateField('Zahlungsdatum')
    rechnungsnummer = models.CharField('Firma', max_length=50)
    kostentyp = models.CharField('Kostentyp', max_length=10, choices=KOSTENTYP_CHOICES)

    # IMPORTANT: now this field stores m³ (not liters)
    gas_volume = models.DecimalField('Gasvolumen (m³)', max_digits=10, decimal_places=2, null=True, blank=True)

    betrag = models.DecimalField('Betrag (€)', max_digits=10, decimal_places=2)
    beschreibung = models.TextField('Beschreibung', blank=True)

    @property
    def gas_volume_liter(self):
        # Liter = m³ / 0.75
        if self.kostentyp == 'helium' and self.gas_volume:
            return self.gas_volume / Decimal("0.75")
        return None

    @property
    def price_per_m3(self):
        if self.kostentyp == 'helium' and self.gas_volume:
            return self.betrag / self.gas_volume
        return None

    @property
    def price_per_liter(self):
        # Preis(Liter) = betrag / liter
        liters = self.gas_volume_liter
        if self.kostentyp == 'helium' and liters:
            return self.betrag / liters
        return None

# Or simpler: Just store row calculations in a JSONField
class TableConfig(models.Model):
    """Configuration for table calculations"""
    table_type = models.CharField(max_length=20, unique=True, choices=[
        ('top_left', 'Top Left Table'),
        ('top_right', 'Top Right Table'),
        ('bottom_1', 'Bottom Table 1'),
        ('bottom_2', 'Bottom Table 2'),
        ('bottom_3', 'Bottom Table 3'),
    ])
    calculations = models.JSONField(default=dict)  # {11: "10 + 9", 15: "14 - 13"}
    
    def __str__(self):
        return f"{self.get_table_type_display()} Config"
class ExcelEntry(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    date = models.DateField(default=timezone.now)
    pressure = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        validators=[MinValueValidator(0)],
        default=0.00
    )
    purity = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        default=0.00
    )
    notes = models.TextField(blank=True, null=True)
    date_joined = models.DateField(auto_now_add=True)

    # Manual input
    lhe_zus = models.DecimalField(
        max_digits=10,
        decimal_places=3,
        validators=[MinValueValidator(0)],
        default=0.0
    )

    druckkorrektur = models.DecimalField(
        max_digits=10,
        decimal_places=3,
        validators=[MinValueValidator(0)],
        default=1.0
    )

    # Auto-calculated values (saved)
    constant_300 = models.DecimalField(
        max_digits=10,
        decimal_places=3,
        default=300.0
    )

    korrig_druck = models.DecimalField(
        max_digits=12,
        decimal_places=6,
        default=0.0
    )

    nm3 = models.DecimalField(
        max_digits=12,
        decimal_places=6,
        default=0.0
    )

    lhe = models.DecimalField(
        max_digits=12,
        decimal_places=6,
        default=0.0
    )

    lhe_ges = models.DecimalField(
        max_digits=12,
        decimal_places=6,
        default=0.0
    )
    
    def __str__(self):
        return f"{self.client.name} - {self.date}"

class SecondTableEntry(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    date = models.DateField(default=timezone.now)
    is_warm = models.BooleanField(default=False)
    lhe_delivery = models.CharField(max_length=100, blank=True, null=True)
    vor = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    nach = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    lhe_output = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        validators=[MinValueValidator(0)],
        blank=True,
        null=True
    )
    notes = models.TextField(blank=True, null=True)
    date_joined = models.DateField(auto_now_add=True)
    class Meta:
        ordering = ["date", "id"]
    def __str__(self):
        return f"{self.client.name} - {self.date}"
    
class MonthlySummary(models.Model):
    """
    Stores per-month summary values that we need in other months
    or in the half-year overview.
    """
    sheet = models.OneToOneField(
        MonthlySheet,
        on_delete=models.CASCADE,
        related_name='summary',
    )

    # K44: Gesamtbestand neu (Lit. LHe) from Bottom Table 2
    gesamtbestand_neu_lhe = models.DecimalField(
        max_digits=18,
        decimal_places=6,
        null=True,
        blank=True,
    )

    # Gasbestand (Lit. LHe) from Bottom Table 1
    gasbestand_lhe = models.DecimalField(
        max_digits=18,
        decimal_places=6,
        null=True,
        blank=True,
    )

    # Verbraucherverluste (Lit. L-He) from overall summary
    verbraucherverlust_lhe = models.DecimalField(
        max_digits=18,
        decimal_places=6,
        null=True,
        blank=True,
    )

    def __str__(self):
        return f"Summary {self.sheet.year}-{self.sheet.month:02d}"
    

class BetriebskostenSummary(models.Model):
    personalkosten = models.DecimalField(max_digits=12, decimal_places=2, default=0)

    instandhaltung = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    heliumkosten = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    bezugskosten_gashe = models.DecimalField(max_digits=12, decimal_places=4, default=0)
    umlage_personal = models.DecimalField(max_digits=12, decimal_places=2, default=0)

    def recalculate(self):
   

        items = Betriebskosten.objects.all()

        sach_sum = items.filter(kostentyp='sach').aggregate(
            total=Coalesce(Sum('betrag'), Value(0, output_field=DecimalField()))
        )['total'] or Decimal('0')

        helium_sum = items.filter(kostentyp='helium').aggregate(
            total=Coalesce(Sum('betrag'), Value(0, output_field=DecimalField()))
        )['total'] or Decimal('0')

        helium_m3_sum = items.filter(kostentyp='helium').aggregate(
            total=Coalesce(Sum('gas_volume'), Value(0, output_field=DecimalField()))
        )['total'] or Decimal('0')

        bezug = (helium_sum / helium_m3_sum) if helium_m3_sum not in (None, 0, Decimal('0')) else Decimal('0')

        self.instandhaltung = sach_sum
        self.heliumkosten = helium_sum
        self.bezugskosten_gashe = bezug
        self.umlage_personal = self.personalkosten / 2
        self.save()

# models.py


class AbrechnungCell(models.Model):
    """
    Storage for the 'Abrechnung' page where columns are custom (not 1:1 with Client).
    Values are saved by: (interval_year, interval_start_month, row_key, col_key).
    """
    interval_year = models.IntegerField()
    interval_start_month = models.IntegerField()  # first month of the 6-month window

    row_key = models.CharField(max_length=60)
    col_key = models.CharField(max_length=60)

    value = models.DecimalField(max_digits=18, decimal_places=6, null=True, blank=True)

    class Meta:
        unique_together = ("interval_year", "interval_start_month", "row_key", "col_key")

    def __str__(self):
        return f"Abrechnung {self.interval_year}/{self.interval_start_month} {self.row_key}:{self.col_key}={self.value}"
