from django.db import models
from django.utils.timezone import now, timedelta
from accounts.models import Organization


class Student(models.Model):
    org            = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='students')
    name           = models.CharField(max_length=150)
    dob            = models.CharField(max_length=20, blank=True)
    gender         = models.CharField(max_length=10, blank=True)
    guardian_name  = models.CharField(max_length=150, blank=True)
    phone          = models.CharField(max_length=20, blank=True)
    email          = models.EmailField(blank=True)
    address        = models.TextField(blank=True)
    batch_or_class = models.CharField(max_length=100, blank=True, help_text="e.g. 'Class 10', 'UPSC Batch A'")

    # Fee — if blank, org's default_monthly_fee is used
    monthly_fee    = models.IntegerField(null=True, blank=True)

    photo_base64   = models.TextField(blank=True)  # from Aadhaar residentImage, if collected

    admission_date = models.DateField(default=now)
    is_active      = models.BooleanField(default=True)

    # How this student was created — useful for admin visibility
    added_via_qr   = models.BooleanField(default=False)

    created_at     = models.DateTimeField(auto_now_add=True)
    updated_at     = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.name} — {self.org.name}"

    def effective_monthly_fee(self):
        if self.monthly_fee is not None:
            return self.monthly_fee
        return self.org.default_monthly_fee or 0

    def fee_status_for_month(self, month_str):
        """month_str format: 'YYYY-MM'. Returns True if a payment record
        covering this month exists for this student."""
        return self.fee_payments.filter(month=month_str).exists()

    class Meta:
        ordering = ['name']


class Attendance(models.Model):
    """
    One row per IN or OUT event. A student's daily visits toggle:
    odd-numbered scan of the day = IN, even-numbered = OUT.
    The 'attendance date' runs 4:00 AM to 4:00 AM (a session after
    midnight but before 4 AM still counts as the previous day).
    """
    org         = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='attendance_records')
    student     = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='attendance_records')
    date        = models.DateField()             # the attendance-day (4AM boundary applied)
    event       = models.CharField(max_length=3, choices=[('IN', 'In'), ('OUT', 'Out')])
    timestamp   = models.DateTimeField(default=now)

    class Meta:
        ordering = ['-timestamp']

    def __str__(self):
        return f"{self.student.name} — {self.event} — {self.timestamp}"

    @staticmethod
    def attendance_date_for(dt):
        """Returns the 'attendance date' for a given datetime, treating
        00:00–03:59 as still belonging to the previous calendar day."""
        local_dt = dt
        if local_dt.hour < 4:
            return (local_dt - timedelta(days=1)).date()
        return local_dt.date()

    @classmethod
    def record_scan(cls, org, student):
        """Call this on every successful QR verification for a student.
        Automatically toggles IN/OUT based on today's (4AM-boundary) events."""
        ts   = now()
        day  = cls.attendance_date_for(ts)

        last_event = cls.objects.filter(
            org=org, student=student, date=day
        ).order_by('-timestamp').first()

        next_event = 'OUT' if (last_event and last_event.event == 'IN') else 'IN'

        record = cls.objects.create(
            org=org, student=student, date=day,
            event=next_event, timestamp=ts,
        )
        return record


class FeePayment(models.Model):
    org         = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='fee_payments')
    student     = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='fee_payments')
    month       = models.CharField(max_length=7, help_text="Format: YYYY-MM")
    amount      = models.IntegerField()
    paid_date   = models.DateField(default=now)
    method      = models.CharField(max_length=30, blank=True, help_text="Cash, UPI, Bank Transfer, etc.")
    notes       = models.TextField(blank=True)
    recorded_by = models.CharField(max_length=150, blank=True)
    created_at  = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-paid_date']
        unique_together = ('student', 'month')

    def __str__(self):
        return f"{self.student.name} — {self.month} — ₹{self.amount}"
