from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from decimal import Decimal
from django.db.models.signals import post_save
from django.dispatch import receiver

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    # Add any extra profile fields if needed in the future
    
    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.get_or_create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    if hasattr(instance, 'profile'):
        instance.profile.save()

class Project(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    supervisors = models.ManyToManyField(User, related_name='assigned_projects')
    active = models.BooleanField(default=True)
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)

    def __str__(self):
        return self.name

class Worker(models.Model):
    name = models.CharField(max_length=200)
    id_number = models.CharField(max_length=50, unique=True)
    phone_number = models.CharField(max_length=20, blank=True)
    monthly_salary = models.DecimalField(max_digits=10, decimal_places=2)
    photo = models.ImageField(upload_to='workers/photos/', blank=True, null=True)
    id_document = models.FileField(upload_to='workers/documents/', blank=True, null=True)
    employment_date = models.DateField(default=timezone.now)
    notes = models.TextField(blank=True)
    active = models.BooleanField(default=True)

    # === SIZING ===
    # Clothing and boot sizes for PPE (personal protective equipment) ordering
    shoe_size = models.CharField(max_length=20, blank=True)
    overall_top_size = models.CharField(max_length=10, blank=True)
    pants_size = models.CharField(max_length=20, blank=True)
    tshirt_size = models.CharField(max_length=10, blank=True)

    # === DRIVERS LICENSE ===
    # Track which workers have a valid drivers license and store a scanned copy
    has_drivers_license = models.BooleanField(default=False)
    drivers_license = models.FileField(upload_to='workers/documents/', blank=True, null=True)

    @property
    def daily_rate(self):
        # monthly salary divided by 20 working days
        return (self.monthly_salary / Decimal('20.00')).quantize(Decimal('0.01'))

    def __str__(self):
        return self.name

class Team(models.Model):
    # === PAY FREQUENCY CHOICES ===
    # Used for the team's recurring pay schedule (weekly, fortnightly, or monthly)
    PAY_FREQUENCY_CHOICES = [
        ('weekly', 'Weekly'),
        ('fortnightly', 'Fortnightly'),
        ('monthly', 'Monthly'),
    ]

    name = models.CharField(max_length=200)
    workers = models.ManyToManyField(Worker, related_name='teams')
    supervisor = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='supervised_teams')
    active = models.BooleanField(default=True)

    # === PAY SCHEDULE ===
    # These two fields define when the team gets paid.
    # pay_start_date is the anchor — the first day of the very first pay period.
    # pay_frequency determines the length of each recurring period.
    # Both are optional — teams without a schedule work as before.
    pay_frequency = models.CharField(max_length=15, choices=PAY_FREQUENCY_CHOICES, blank=True, default='')
    pay_start_date = models.DateField(blank=True, null=True, help_text='Anchor date for first pay period')

    def __str__(self):
        return self.name

class WorkLog(models.Model):
    OVERTIME_CHOICES = [
        (Decimal('0.00'), 'None'),
        (Decimal('0.25'), '1/4 Day'),
        (Decimal('0.50'), '1/2 Day'),
        (Decimal('0.75'), '3/4 Day'),
        (Decimal('1.00'), 'Full Day'),
    ]

    date = models.DateField(default=timezone.now)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='work_logs')
    team = models.ForeignKey(Team, on_delete=models.SET_NULL, null=True, blank=True, related_name='work_logs')
    workers = models.ManyToManyField(Worker, related_name='work_logs')
    supervisor = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='work_logs_created')
    notes = models.TextField(blank=True)
    overtime_amount = models.DecimalField(max_digits=3, decimal_places=2, choices=OVERTIME_CHOICES, default=Decimal('0.00'))
    priced_workers = models.ManyToManyField(Worker, related_name='priced_overtime_logs', blank=True)

    @property
    def display_amount(self):
        """Total daily cost for all workers on this log (sum of daily_rate).
        Works efficiently with prefetch_related('workers')."""
        return sum(w.daily_rate for w in self.workers.all())

    def __str__(self):
        return f"{self.date} - {self.project.name}"

class PayrollRecord(models.Model):
    worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name='payroll_records')
    date = models.DateField(default=timezone.now)
    amount_paid = models.DecimalField(max_digits=10, decimal_places=2)
    work_logs = models.ManyToManyField(WorkLog, related_name='payroll_records')

    def __str__(self):
        return f"{self.worker.name} - {self.date}"

class Loan(models.Model):
    # === LOAN TYPE ===
    # 'loan' = traditional loan (created via "New Loan")
    # 'advance' = salary advance (created via "Advance Payment")
    # Both work the same way (tracked balance, repayments) but are
    # labelled differently on payslips and in the Loans tab.
    LOAN_TYPE_CHOICES = [
        ('loan', 'Loan'),
        ('advance', 'Advance'),
    ]

    worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name='loans')
    loan_type = models.CharField(max_length=10, choices=LOAN_TYPE_CHOICES, default='loan')
    principal_amount = models.DecimalField(max_digits=10, decimal_places=2)
    remaining_balance = models.DecimalField(max_digits=10, decimal_places=2)
    date = models.DateField(default=timezone.now)
    reason = models.TextField(blank=True)
    active = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        if not self.pk:
            self.remaining_balance = self.principal_amount
        super().save(*args, **kwargs)

    def __str__(self):
        label = 'Advance' if self.loan_type == 'advance' else 'Loan'
        return f"{self.worker.name} - {label} - {self.date}"

class PayrollAdjustment(models.Model):
    TYPE_CHOICES = [
        ('Bonus', 'Bonus'),
        ('Overtime', 'Overtime'),
        ('Deduction', 'Deduction'),
        ('Loan Repayment', 'Loan Repayment'),
        ('New Loan', 'New Loan'),
        ('Advance Payment', 'Advance Payment'),
        ('Advance Repayment', 'Advance Repayment'),
    ]

    worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name='adjustments')
    payroll_record = models.ForeignKey(PayrollRecord, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments')
    loan = models.ForeignKey(Loan, on_delete=models.SET_NULL, null=True, blank=True, related_name='repayments')
    work_log = models.ForeignKey(WorkLog, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments_by_work_log')
    project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments_by_project')
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    date = models.DateField(default=timezone.now)
    description = models.TextField(blank=True)
    type = models.CharField(max_length=50, choices=TYPE_CHOICES)

    def __str__(self):
        return f"{self.worker.name} - {self.type} - {self.amount}"

class ExpenseReceipt(models.Model):
    METHOD_CHOICES = [
        ('Cash', 'Cash'),
        ('Card', 'Card'),
        ('EFT', 'EFT'),
        ('Other', 'Other'),
    ]
    VAT_CHOICES = [
        ('Included', 'Included'),
        ('Excluded', 'Excluded'),
        ('None', 'None'),
    ]

    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='expense_receipts')
    date = models.DateField(default=timezone.now)
    vendor_name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    payment_method = models.CharField(max_length=20, choices=METHOD_CHOICES)
    vat_type = models.CharField(max_length=20, choices=VAT_CHOICES)
    subtotal = models.DecimalField(max_digits=12, decimal_places=2)
    vat_amount = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
    total_amount = models.DecimalField(max_digits=12, decimal_places=2)

    def __str__(self):
        return f"{self.vendor_name} - {self.date}"

class ExpenseLineItem(models.Model):
    receipt = models.ForeignKey(ExpenseReceipt, on_delete=models.CASCADE, related_name='line_items')
    product_name = models.CharField(max_length=200)
    amount = models.DecimalField(max_digits=12, decimal_places=2)

    def __str__(self):
        return self.product_name
