from django.conf import settings
from django.db import models
from apps.core.models import TimeStampedModel
from apps.employees.models import Employee


class LoanAccount(TimeStampedModel):
    class Status(models.TextChoices):
        PENDING_DISBURSEMENT = "PENDING_DISBURSEMENT", "Pending Disbursement"
        ACTIVE = "ACTIVE", "Active"
        CLOSED = "CLOSED", "Closed"
        CANCELLED = "CANCELLED", "Cancelled"

    class LoanType(models.TextChoices):
        LOAN = "LOAN", "Employee Loan"
        SALARY_ADVANCE = "SALARY_ADVANCE", "Salary Advance"

    employee = models.ForeignKey(Employee, on_delete=models.PROTECT, related_name="loan_accounts")
    loan_type = models.CharField(max_length=30, choices=LoanType.choices, default=LoanType.LOAN)
    request_reference = models.CharField(max_length=60, blank=True, db_index=True)
    requested_amount = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    sanctioned_amount = models.DecimalField(max_digits=14, decimal_places=2)
    installment_amount = models.DecimalField(max_digits=14, decimal_places=2)
    installment_count = models.PositiveIntegerField(default=1)
    start_month = models.DateField()
    sanctioned_at = models.DateTimeField(null=True, blank=True)
    disbursement_date = models.DateField(null=True, blank=True)
    disbursement_reference = models.CharField(max_length=120, blank=True)
    outstanding_balance = models.DecimalField(max_digits=14, decimal_places=2)
    status = models.CharField(max_length=30, choices=Status.choices, default=Status.PENDING_DISBURSEMENT)
    reason = models.TextField(blank=True)

    class Meta:
        indexes = [
            models.Index(fields=["employee", "status"]),
            models.Index(fields=["request_reference"]),
        ]


class LoanInstallment(TimeStampedModel):
    class Status(models.TextChoices):
        DUE = "DUE", "Due"
        PARTIAL = "PARTIAL", "Partially Paid"
        PAID = "PAID", "Paid"

    loan = models.ForeignKey(LoanAccount, on_delete=models.PROTECT, related_name="installments")
    due_month = models.DateField()
    due_amount = models.DecimalField(max_digits=14, decimal_places=2)
    paid_amount = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    payroll_reference = models.CharField(max_length=120, blank=True)
    status = models.CharField(max_length=20, choices=Status.choices, default=Status.DUE)

    class Meta:
        ordering = ["due_month", "pk"]
        constraints = [models.UniqueConstraint(fields=["loan", "due_month"], name="uq_loan_due_month")]


class LoanRecovery(TimeStampedModel):
    """Posted recovery ledger. Reversible when an already locked payroll is unlocked."""

    loan = models.ForeignKey(LoanAccount, on_delete=models.PROTECT, related_name="recoveries")
    installment = models.ForeignKey(LoanInstallment, on_delete=models.PROTECT, related_name="recoveries")
    payroll_record = models.ForeignKey("payroll.PayrollRecord", on_delete=models.PROTECT, related_name="loan_recovery_entries")
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    idempotency_key = models.CharField(max_length=120, unique=True)
    is_reversed = models.BooleanField(default=False)
    reversed_at = models.DateTimeField(null=True, blank=True)
    reversed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name="reversed_loan_recoveries")

    class Meta:
        ordering = ["created_at", "pk"]


class ExitLoanSettlement(TimeStampedModel):
    """Final-settlement loan recovery ledger independent of monthly payroll."""
    loan = models.ForeignKey(LoanAccount, on_delete=models.PROTECT, related_name="exit_settlements")
    final_settlement = models.ForeignKey("exits.FinalSettlement", on_delete=models.PROTECT, related_name="loan_settlement_entries")
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    idempotency_key = models.CharField(max_length=120, unique=True)
    posted_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name="posted_exit_loan_settlements")

    class Meta:
        ordering = ["created_at", "pk"]
