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 Project(models.Model):
    """Project management."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    status = models.CharField(max_length=20, choices=[
        ("planning", "Planning"),
        ("active", "Active"),
        ("on_hold", "On Hold"),
        ("completed", "Completed"),
        ("archived", "Archived"),
    ], default="planning")
    lead = models.ForeignKey(
        "hr.Employee",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="led_projects",
    )
    start_date = models.DateField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)
    tags = models.JSONField(default=list)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "projects"
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["status"]),
            models.Index(fields=["start_date"]),
            models.Index(fields=["end_date"]),
        ]

    def __str__(self):
        return self.name


class ProjectDocument(models.Model):
    """Documents attached to projects."""
    ACCESS_PUBLIC = "public"
    ACCESS_RESTRICTED = "restricted"
    ACCESS_CHOICES = [(ACCESS_PUBLIC, "Public"), (ACCESS_RESTRICTED, "Restricted")]

    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="documents")
    name = models.CharField(max_length=255)
    file = models.FileField(upload_to="project_documents/%Y/%m/")
    uploaded_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
    access_level = models.CharField(max_length=20, choices=ACCESS_CHOICES, default=ACCESS_PUBLIC)
    # When access_level=restricted, only uploader + these users can read.
    allowed_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        blank=True,
        related_name="accessible_project_documents",
    )
    created_at = models.DateTimeField(auto_now_add=True)

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

    def can_be_read_by(self, user) -> bool:
        if self.access_level == self.ACCESS_PUBLIC:
            return True
        if not getattr(user, "is_authenticated", False):
            return False
        if user.is_superuser:
            return True
        if self.uploaded_by_id == user.id:
            return True
        return self.allowed_users.filter(id=user.id).exists()

    @classmethod
    def visible_to(cls, queryset, user):
        """DB-level equivalent of can_be_read_by. Apply on a ProjectDocument queryset."""
        from django.db.models import Q
        public_q = Q(access_level=cls.ACCESS_PUBLIC)
        if not getattr(user, "is_authenticated", False):
            return queryset.filter(public_q)
        if user.is_superuser:
            return queryset
        return queryset.filter(
            public_q | Q(uploaded_by_id=user.id) | Q(allowed_users=user)
        ).distinct()


class ProjectTeamMember(models.Model):
    """Team members assigned to projects."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="team_members")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="project_memberships")
    role = models.CharField(max_length=20, choices=[
        ("owner", "Owner"),
        ("manager", "Manager"),
        ("member", "Member"),
        ("viewer", "Viewer"),
    ], default="member")
    joined_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "project_team_members"
        unique_together = ["project", "user"]
        ordering = ["role", "joined_at"]


class ProjectFinance(models.Model):
    """Income/expense ledger entries per project."""
    LEDGER_CHOICES = [
        ("general", "General Ledger"),
        ("project", "Project Ledger"),
        ("event", "Event Budget Ledger"),
        ("expense", "Expense Ledger"),
        ("apar", "AP/AR Ledger"),
        ("procurement", "Procurement Ledger"),
        ("grant", "Grant Ledger"),
        ("asset", "Asset Ledger"),
        ("cashbank", "Cash/Bank Ledger"),
        ("audit", "Audit Ledger"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="finance_entries")
    description = models.CharField(max_length=255)
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    currency = models.CharField(max_length=10, default="IDR")
    type = models.CharField(max_length=10, choices=[("income", "Income"), ("expense", "Expense")], default="expense")
    ledger = models.CharField(max_length=20, choices=LEDGER_CHOICES, default="general")
    category = models.CharField(max_length=100, blank=True)
    budget_category = models.ForeignKey(
        "finance.BudgetCategory", on_delete=models.SET_NULL, null=True, blank=True,
        related_name="project_finance_entries", help_text="Budget category this entry maps to.",
    )
    budget_item = models.ForeignKey(
        "finance.BudgetItem", on_delete=models.SET_NULL, null=True, blank=True,
        related_name="finance_entries", help_text="Budget item (catalog code) this entry maps to.",
    )
    date = models.DateField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_finance"
        ordering = ["-date", "-created_at"]
        indexes = [
            models.Index(fields=["type"]),
            models.Index(fields=["ledger"]),
            models.Index(fields=["date"]),
            models.Index(fields=["project", "type"]),
            models.Index(fields=["project", "date"]),
        ]


class ProjectDissemination(models.Model):
    """Outreach / dissemination tied to a project. Optionally references an Event or Publication."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="disseminations")
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    date = models.DateField(null=True, blank=True)
    location = models.CharField(max_length=255, blank=True)
    event = models.ForeignKey(
        "events.Event",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="project_disseminations",
    )
    publication = models.ForeignKey(
        "publications.Publication",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="project_disseminations",
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_disseminations"
        ordering = ["-date", "-created_at"]


class ProjectFund(models.Model):
    """Funding source for a project. A project may have multiple funds."""
    STATUS_CHOICES = [
        ("proposed", "Proposed"),
        ("pledged", "Pledged"),
        ("received", "Received"),
        ("allocated", "Allocated"),
        ("closed", "Closed"),
        ("rejected", "Rejected"),
    ]
    FUND_TYPE_CHOICES = [
        ("grant", "Grant"),
        ("sponsorship", "Sponsorship"),
        ("donation", "Donation"),
        ("cofunding", "Co-funding"),
        ("other", "Other"),
    ]
    CONVERSION_TIMING_CHOICES = [
        ("on_arrival", "Convert when fund arrives"),
        ("on_payment", "Convert when you pay"),
        ("on_project_end", "Convert by the end of the project"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(
        Project, on_delete=models.SET_NULL, related_name="funds",
        null=True, blank=True,
        help_text="Owning project. Null while the fund is still a prospect/proposal (fund-first flow).",
    )
    source = models.CharField(max_length=255, help_text="Donor / grantor / funding body name")
    fund_type = models.CharField(
        max_length=20, choices=FUND_TYPE_CHOICES, default="grant", db_index=True,
        help_text="Funding mechanism. 'grant' is the most common subset.",
    )
    donor = models.ForeignKey(
        "companies.Company",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="funds_provided",
        help_text="Canonical donor record. Auto-linked by name when missing.",
    )
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    currency = models.CharField(max_length=10, default="IDR")
    # IDR is the reporting currency. For foreign funds we store the FX rate on the
    # received date and the converted amount (auto-fetched in the ViewSet).
    exchange_rate = models.DecimalField(
        max_digits=18, decimal_places=6, null=True, blank=True,
        help_text="IDR per 1 unit of currency, on received_date. 1 for IDR.",
    )
    amount_idr = models.DecimalField(
        max_digits=20, decimal_places=2, null=True, blank=True,
        help_text="amount converted to IDR at exchange_rate.",
    )
    conversion_timing = models.CharField(
        max_length=20, choices=CONVERSION_TIMING_CHOICES, default="on_arrival",
        help_text="When the FX rate for this fund's conversions is taken.",
    )
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="pledged")
    frozen = models.BooleanField(
        default=False, db_index=True,
        help_text="Frozen funds are locked: no edits or new allocations until unfrozen.",
    )
    agreement_date = models.DateField(null=True, blank=True)
    received_date = models.DateField(null=True, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_funds"
        ordering = ["-agreement_date", "-created_at"]
        indexes = [
            # Cash statements/reports filter funds by lifecycle status.
            models.Index(fields=["status"]),
        ]

    def __str__(self):
        return f"{self.source} — {self.project.name if self.project else 'Unassigned'}"


class ProjectFundAllocation(models.Model):
    """Allocates part of a fund's amount to a budget item (catalog code, e.g. B.1)."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="allocations")
    budget_item = models.ForeignKey(
        "finance.BudgetItem", on_delete=models.PROTECT, related_name="allocations",
        help_text="Budget item this slice maps to.",
    )
    # Grant budget-line breakdown. amount = quantity * unit_cost(fund ccy)
    # * frequency * (time_allocated_pct / 100), computed on save.
    unit = models.CharField(max_length=50, blank=True, help_text="Unit label, e.g. person, month, trip.")
    quantity = models.DecimalField(max_digits=12, decimal_places=2, default=1)
    frequency = models.DecimalField(max_digits=12, decimal_places=2, default=1)
    unit_cost = models.DecimalField(max_digits=14, decimal_places=2, default=0, help_text="Unit cost as entered, in unit_cost_currency.")
    unit_cost_currency = models.CharField(max_length=10, blank=True, help_text="Currency of unit_cost; defaults to the fund currency.")
    unit_cost_fund_ccy = models.DecimalField(
        max_digits=14, decimal_places=2, default=0,
        help_text="unit_cost converted to the fund currency (used in amount).",
    )
    time_allocated_pct = models.DecimalField(max_digits=6, decimal_places=2, default=100)
    amount = models.DecimalField(max_digits=14, decimal_places=2, default=0, help_text="Computed, in fund currency.")
    note = models.CharField(max_length=255, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        from decimal import Decimal
        from .fx import convert_between

        fund_ccy = (self.fund.currency if self.fund_id else "IDR") or "IDR"
        cost_ccy = (self.unit_cost_currency or fund_ccy).upper()
        self.unit_cost_currency = cost_ccy

        converted = convert_between(self.unit_cost or Decimal("0"), cost_ccy, fund_ccy, self.fund if self.fund_id else None)
        self.unit_cost_fund_ccy = converted if converted is not None else (self.unit_cost or Decimal("0"))

        self.amount = (
            (self.quantity or 0) * (self.unit_cost_fund_ccy or 0) * (self.frequency or 0)
            * (self.time_allocated_pct or 0) / 100
        )
        super().save(*args, **kwargs)

    class Meta:
        db_table = "project_fund_allocations"
        ordering = ["-created_at"]
        constraints = [
            models.UniqueConstraint(fields=["fund", "budget_item"], name="uniq_fund_budget_item"),
        ]
        indexes = [models.Index(fields=["fund"])]

    def __str__(self):
        return f"{self.fund_id} → {self.budget_item_id}: {self.amount}"


class ProjectSchedule(models.Model):
    """Project milestones / scheduled phases."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="schedule_items")
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    start_date = models.DateField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_schedule"
        ordering = ["start_date", "-created_at"]


class ProjectSettings(models.Model):
    """Singleton settings for the Projects module — access rules and the
    AI-seeded proposal/report templates."""
    ACCESS_LEVELS = [
        ("everyone", "Everyone in the organization"),
        ("members", "Project team members only"),
        ("admins", "Administrators only"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)

    access_level = models.CharField(max_length=20, choices=ACCESS_LEVELS, default="members")
    donor_pic_can_access = models.BooleanField(default=False)

    proposal_template = models.TextField(blank=True)
    report_template = models.TextField(blank=True)

    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_settings"

    def __str__(self):
        return "Project Settings"

class FundingOpportunity(models.Model):
    """An open call / prospect this fund originated from — tracked before a
    proposal is submitted."""
    STAGE_CHOICES = [
        ("screening", "Screening"),
        ("applying", "Applying"),
        ("converted", "Converted"),
        ("dropped", "Dropped"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="opportunities")
    name = models.CharField(max_length=255)
    donor = models.ForeignKey(
        "companies.Company", on_delete=models.SET_NULL, null=True, blank=True,
        related_name="funding_opportunities",
    )
    deadline = models.DateField(null=True, blank=True)
    ceiling = models.DecimalField(max_digits=14, decimal_places=2, null=True, blank=True)
    stage = models.CharField(max_length=20, choices=STAGE_CHOICES, default="screening", db_index=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "funding_opportunities"
        ordering = ["-created_at"]
        indexes = [models.Index(fields=["fund"])]

    def __str__(self):
        return self.name


class FundingProposal(models.Model):
    """A drafted/submitted proposal tied to a funding source."""
    STATUS_CHOICES = [
        ("draft", "Draft"),
        ("under_review", "Under review"),
        ("approved", "Approved"),
        ("declined", "Declined"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="proposals")
    title = models.CharField(max_length=255)
    submitted_date = models.DateField(null=True, blank=True)
    requested_amount = models.DecimalField(max_digits=14, decimal_places=2, null=True, blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="draft", db_index=True)
    document = models.FileField(upload_to="funding_proposals/", null=True, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "funding_proposals"
        ordering = ["-created_at"]
        indexes = [models.Index(fields=["fund"])]

    def __str__(self):
        return self.title


class FundReport(models.Model):
    """A narrative/financial report owed to the donor under an agreement."""
    KIND_CHOICES = [
        ("narrative", "Narrative"),
        ("financial", "Financial"),
        ("final", "Final"),
    ]
    STATUS_CHOICES = [
        ("upcoming", "Upcoming"),
        ("submitted", "Submitted"),
        ("overdue", "Overdue"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="reports")
    title = models.CharField(max_length=255)
    kind = models.CharField(max_length=20, choices=KIND_CHOICES, default="narrative")
    due_date = models.DateField(null=True, blank=True)
    submitted_date = models.DateField(null=True, blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="upcoming", db_index=True)
    document = models.FileField(upload_to="fund_reports/", null=True, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "fund_reports"
        ordering = ["due_date", "-created_at"]
        indexes = [models.Index(fields=["fund"])]

    def __str__(self):
        return self.title


class ProjectFundTranche(models.Model):
    """A scheduled/received disbursement (milestone payment) of a fund."""
    STATUS_CHOICES = [
        ("scheduled", "Scheduled"),
        ("received", "Received"),
        ("overdue", "Overdue"),
        ("cancelled", "Cancelled"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="tranches")
    label = models.CharField(max_length=255)
    amount = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    expected_date = models.DateField(null=True, blank=True)
    received_date = models.DateField(null=True, blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="scheduled", db_index=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_fund_tranches"
        ordering = ["expected_date", "-created_at"]
        indexes = [models.Index(fields=["fund"])]

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


class ProjectFundCompliance(models.Model):
    """A compliance/audit obligation owed under a funding agreement."""
    KIND_CHOICES = [
        ("report", "Report"),
        ("audit", "Audit"),
        ("submission", "Submission"),
    ]
    STATUS_CHOICES = [
        ("upcoming", "Upcoming"),
        ("submitted", "Submitted"),
        ("overdue", "Overdue"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="compliance_items")
    title = models.CharField(max_length=255)
    kind = models.CharField(max_length=20, choices=KIND_CHOICES, default="report")
    due_date = models.DateField(null=True, blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="upcoming", db_index=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_fund_compliance"
        ordering = ["due_date", "-created_at"]
        indexes = [models.Index(fields=["fund"])]

    def __str__(self):
        return self.title


class FundDocument(models.Model):
    """A document attached to a fund, classified by category.

    Unifies proposals, agreements, donor reports, and compliance/audit items
    behind one model so the fund Documents tab is a single store with a
    category filter.
    """
    CATEGORY_CHOICES = [
        ("proposal", "Proposal"),
        ("agreement", "Agreement"),
        ("reporting", "Reporting"),
        ("compliance", "Compliance & Audit"),
    ]
    STATUS_CHOICES = [
        ("draft", "Draft"),
        ("submitted", "Submitted"),
        ("approved", "Approved"),
        ("signed", "Signed"),
        ("overdue", "Overdue"),
    ]
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    fund = models.ForeignKey(ProjectFund, on_delete=models.CASCADE, related_name="fund_documents")
    category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, default="proposal", db_index=True)
    title = models.CharField(max_length=255)
    document = models.FileField(upload_to="fund_documents/", null=True, blank=True)
    date = models.DateField(null=True, blank=True, help_text="Signed / submitted / due date depending on category.")
    amount = models.DecimalField(max_digits=14, decimal_places=2, null=True, blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "fund_documents"
        ordering = ["-date", "-created_at"]
        indexes = [models.Index(fields=["fund", "category"])]

    def __str__(self):
        return f"{self.get_category_display()}: {self.title}"


class ProjectResource(models.Model):
    """Research data sources and literature used in a project."""

    KIND_CHOICES = [
        ("data", "Data"),
        ("literature", "Literature"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="resources")
    kind = models.CharField(max_length=20, choices=KIND_CHOICES)
    title = models.CharField(max_length=255)
    link = models.URLField(max_length=1000, blank=True)
    # data-only
    detail = models.TextField(blank=True)
    source = models.CharField(max_length=255, blank=True)
    # shared
    year = models.PositiveIntegerField(null=True, blank=True)
    # literature-only
    authors = models.CharField(max_length=500, blank=True)
    publisher = models.CharField(max_length=255, blank=True)
    lit_type = models.CharField(
        max_length=20,
        blank=True,
        choices=[
            ("book", "Book"),
            ("journal", "Journal"),
            ("report", "Report"),
            ("website", "Website"),
            ("other", "Other"),
        ],
    )
    quoted_page = models.CharField(max_length=100, blank=True)
    notes = models.TextField(blank=True)

    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="project_resources",
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "project_resources"
        ordering = ["-created_at"]
        indexes = [models.Index(fields=["project", "kind"])]

    def __str__(self):
        return f"{self.get_kind_display()}: {self.title}"


class ProjectLog(models.Model):
    """Audit log for all project-related actions."""

    LOG_TYPE_CHOICES = [
        ("project", "Project"),
        ("task", "Task"),
        ("document", "Document"),
        ("finance", "Finance"),
        ("fund", "Fund"),
        ("team", "Team"),
        ("dissemination", "Dissemination"),
        ("schedule", "Schedule"),
        ("resource", "Resource"),
        ("status", "Status"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="logs")
    actor = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True,
        related_name="project_logs",
    )
    log_type = models.CharField(max_length=20, choices=LOG_TYPE_CHOICES, default="project")
    action = models.CharField(max_length=255)
    detail = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "project_logs"
        ordering = ["-created_at"]
        indexes = [models.Index(fields=["project", "-created_at"])]

    def __str__(self):
        return f"{self.log_type}: {self.action}"
