from django.db import models
from django.conf import settings
from django.utils import timezone
import secrets
import time


def uuid7() -> str:
    """Generate a UUID v7 (time-ordered UUID)."""
    nanoseconds = time.time_ns()
    uuid_int = (nanoseconds << 16) | secrets.randbits(48)
    return f"{uuid_int:032x}"


class CarBooking(models.Model):
    """Vehicle booking requests."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    requester = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="car_bookings")
    vehicle = models.ForeignKey(
        "asset_management.Asset",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="car_bookings",
    )
    vehicle_name = models.CharField(max_length=100, blank=True)
    purpose = models.TextField()
    start_datetime = models.DateTimeField()
    end_datetime = models.DateTimeField()
    destination = models.CharField(max_length=255)
    number_of_passengers = models.IntegerField(default=1)
    status = models.CharField(max_length=20, choices=[
        ("pending", "Pending"),
        ("approved", "Approved"),
        ("rejected", "Rejected"),
        ("completed", "Completed"),
        ("cancelled", "Cancelled"),
    ], default="pending")
    approved_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="car_booking_approvals")
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "car_bookings"
        ordering = ["-created_at"]


class Reimbursement(models.Model):
    """Expense reimbursement requests."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    requester = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="reimbursements")
    title = models.CharField(max_length=255)
    description = models.TextField()
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    receipts = models.JSONField(default=list)
    status = models.CharField(max_length=20, choices=[
        ("pending", "Pending"),
        ("approved", "Approved"),
        ("rejected", "Rejected"),
        ("paid", "Paid"),
    ], default="pending")
    approved_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True)
    paid_at = models.DateTimeField(null=True, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "reimbursements"
        ordering = ["-created_at"]
        indexes = [
            # Cash statements + list filters select by workflow status.
            models.Index(fields=["status"]),
        ]


class ReimbursementReceipt(models.Model):
    """Uploaded receipt file (image or PDF) for a reimbursement claim."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    reimbursement = models.ForeignKey(
        Reimbursement, on_delete=models.CASCADE, related_name="receipt_files"
    )
    file = models.FileField(upload_to="reimbursement_receipts/")
    uploaded_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True,
        related_name="uploaded_reimbursement_receipts",
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "reimbursement_receipts"
        ordering = ["created_at"]


class PaymentRequest(models.Model):
    """General payment requests."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    requester = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="payment_requests")
    title = models.CharField(max_length=255)
    description = models.TextField()
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    payee = models.CharField(max_length=255)
    bank_account = models.CharField(max_length=100, blank=True)
    status = models.CharField(max_length=20, choices=[
        ("pending", "Pending"),
        ("approved", "Approved"),
        ("rejected", "Rejected"),
        ("paid", "Paid"),
    ], default="pending")
    source_invoice = models.ForeignKey(
        "procurements.Invoice",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="payment_requests",
        help_text="Procurement invoice this payment request was generated from.",
    )
    approved_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True)
    paid_at = models.DateTimeField(null=True, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "payment_requests"
        ordering = ["-created_at"]
        indexes = [
            # Cash statements + list filters select by workflow status.
            models.Index(fields=["status"]),
        ]


class DocumentRequest(models.Model):
    """Document request submissions."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    requester = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="document_requests")
    document_type = models.CharField(max_length=100)
    purpose = models.TextField()
    status = models.CharField(max_length=20, choices=[
        ("pending", "Pending"),
        ("in_progress", "In Progress"),
        ("ready", "Ready"),
        ("rejected", "Rejected"),
    ], default="pending")
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "document_requests"
        ordering = ["-created_at"]


def _to_roman(n):
    """Month number (1-12) → Roman numeral. Indonesian letter-numbering style."""
    numerals = [
        (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I"),
    ]
    result = ""
    for value, sym in numerals:
        while n >= value:
            result += sym
            n -= value
    return result


class LetterPrefix(models.Model):
    """A letter-number type, usually a department/unit code (e.g. EKON for
    Economic department). Managed by secretariat in settings."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    code = models.CharField(max_length=20, unique=True, help_text="Short code shown in the number, e.g. EKON.")
    label = models.CharField(max_length=120, help_text="Full name, e.g. Departemen Ekonomi.")
    description = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "letter_prefixes"
        ordering = ["code"]
        verbose_name_plural = "letter prefixes"

    def __str__(self):
        return f"{self.code} — {self.label}"


class LetterNumber(models.Model):
    """Letter number tracking system. Format: {sequence}/{prefix}/{roman month}/{year},
    e.g. 331/EKON/VI/2026. Sequence continues per prefix and resets each year."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    prefix = models.ForeignKey(
        LetterPrefix, on_delete=models.PROTECT, related_name="letters",
        help_text="Department/unit code this letter belongs to.",
    )
    year = models.IntegerField()
    month = models.IntegerField()
    sequence = models.IntegerField()
    subject = models.CharField(max_length=255)
    recipient = models.TextField()
    sender = models.CharField(max_length=100)
    date = models.DateField()
    file = models.FileField(upload_to="letter_numbers/%Y/%m/", null=True, blank=True)
    notes = models.TextField(blank=True)
    document_request = models.ForeignKey(
        "DocumentRequest", on_delete=models.SET_NULL, null=True, blank=True,
        related_name="letters",
        help_text="Document request this letter was issued to fulfil, if any.",
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "letter_numbers"
        ordering = ["-date"]
        # Sequence resets per year, continues per prefix within a year.
        unique_together = ["prefix", "year", "sequence"]

    @property
    def full_number(self):
        return f"{self.sequence:03d}/{self.prefix.code}/{_to_roman(self.month)}/{self.year}"


class Announcement(models.Model):
    """Company announcements."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    title = models.CharField(max_length=255)
    content = models.TextField()
    priority = models.CharField(max_length=20, choices=[
        ("info", "Info"),
        ("important", "Important"),
        ("urgent", "Urgent"),
    ], default="info")
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="announcements")
    is_pinned = models.BooleanField(default=False)
    valid_from = models.DateTimeField()
    valid_until = models.DateTimeField(null=True, blank=True)
    attachments = models.JSONField(default=list)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "announcements"
        ordering = ["-is_pinned", "-created_at"]


class SOPCategory(models.Model):
    """Managed list of SOP categories. SOP.category stores the name; this model
    is the controlled vocabulary that feeds the category dropdown."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    name = models.CharField(max_length=100, unique=True)
    description = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "sop_categories"
        ordering = ["name"]
        verbose_name_plural = "SOP categories"

    def __str__(self):
        return self.name


class SOP(models.Model):
    """Standard Operating Procedures."""
    STATUS_CHOICES = [
        ("draft", "Draft"),
        ("review", "Review"),
        ("active", "Active"),
        ("obsolete", "Obsolete"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    code = models.CharField(max_length=50, unique=True)
    title = models.CharField(max_length=255)
    category = models.CharField(max_length=100)
    content = models.TextField()
    version = models.CharField(max_length=20, default="1.0")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="draft", db_index=True)
    tags = models.JSONField(default=list, blank=True)
    effective_date = models.DateField()
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
    attachments = models.JSONField(default=list)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "sops"
        ordering = ["code"]


class SOPVersion(models.Model):
    """Immutable snapshot of an SOP at a given version."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    sop = models.ForeignKey(SOP, related_name="versions", on_delete=models.CASCADE)
    version = models.CharField(max_length=20)
    content = models.TextField()
    effective_date = models.DateField()
    change_note = models.CharField(max_length=500, blank=True)
    changed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "sop_versions"
        ordering = ["-created_at"]


class InternalGuide(models.Model):
    """Internal guides and documentation."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    title = models.CharField(max_length=255)
    category = models.CharField(max_length=100)
    content = models.TextField()
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
    tags = models.JSONField(default=list)
    attachments = models.JSONField(default=list)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "internal_guides"
        ordering = ["title"]


class HelpdeskTicket(models.Model):
    """Internal support tickets (IT / HR / Office)."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    ticket_number = models.CharField(max_length=20, unique=True, blank=True)
    requester = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="helpdesk_tickets")
    subject = models.CharField(max_length=255)
    category = models.CharField(max_length=50, blank=True)
    department = models.CharField(max_length=100, blank=True)
    description = models.TextField()
    priority = models.CharField(max_length=20, choices=[
        ("low", "Low"),
        ("medium", "Medium"),
        ("high", "High"),
        ("urgent", "Urgent"),
    ], default="medium")
    status = models.CharField(max_length=20, choices=[
        ("open", "Open"),
        ("in_progress", "In Progress"),
        ("resolved", "Resolved"),
        ("closed", "Closed"),
    ], default="open")
    resolution = models.TextField(blank=True)
    assigned_to = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True,
        related_name="assigned_helpdesk_tickets",
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "helpdesk_tickets"
        ordering = ["-created_at"]
        indexes = [
            # List filters select by workflow status.
            models.Index(fields=["status"]),
        ]

    def save(self, *args, **kwargs):
        if not self.ticket_number:
            # Sequential ticket number HD-00001; assigned on first save.
            last = HelpdeskTicket.objects.order_by("-ticket_number").first()
            seq = int(last.ticket_number.split("-")[1]) + 1 if last and last.ticket_number else 1
            self.ticket_number = f"HD-{seq:05d}"
        super().save(*args, **kwargs)