"""Workbox domain models.

Model inventory
---------------
WorkboxViewType   — enum: my_work / pending_approvals / delegated / overdue / completed
WorkboxItemType   — enum: assignment / approval / task / workflow_step / ticket / review / custom
WorkboxItemStatus — enum: pending / in_progress / overdue / completed / cancelled / expired
WorkItem          — canonical platform-level actionable item (formerly denormalized cache)
WorkItemTimeline  — immutable event log recording every state change on a WorkItem
"""

from __future__ import annotations

from typing import ClassVar

from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from simorgh.core.models import (
    AuditedModel,
    TenantScopedModel,
    UUIDModel,
)


class WorkboxViewType(models.TextChoices):
    MY_WORK           = "my_work",           _("My Work")
    PENDING_APPROVALS = "pending_approvals", _("Pending Approvals")
    DELEGATED         = "delegated",         _("Delegated")
    OVERDUE           = "overdue",           _("Overdue")
    COMPLETED         = "completed",         _("Completed")


class WorkboxItemType(models.TextChoices):
    ASSIGNMENT      = "assignment",      _("Assignment")
    APPROVAL        = "approval",        _("Approval")
    TASK            = "task",            _("Task")
    WORKFLOW_STEP   = "workflow_step",   _("Workflow Step")
    TICKET          = "ticket",          _("Ticket")
    REVIEW          = "review",          _("Review")
    CUSTOM          = "custom",          _("Custom")
    NOTIFICATION    = "notification",    _("Notification")


class WorkboxItemStatus(models.TextChoices):
    PENDING     = "pending",     _("Pending")
    IN_PROGRESS = "in_progress", _("In Progress")
    OVERDUE     = "overdue",     _("Overdue")
    COMPLETED   = "completed",   _("Completed")
    CANCELLED   = "cancelled",   _("Cancelled")
    EXPIRED     = "expired",     _("Expired")


class WorkItem(UUIDModel, TenantScopedModel, AuditedModel):
    """Canonical platform-level actionable item consumed by the Workbox.

    All engines (Assignment, Approval, Task, Workflow, Helpdesk, CRM, HR, DMS)
    MUST create WorkItem records as their canonical source of truth.  The
    Workbox UI layer queries WorkItem directly — no dual-write cache refresh
    is needed.
    """

    assigned_to_user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="work_items_assigned",
        verbose_name=_("assigned to user"),
        db_index=True,
    )
    assigned_to_role = models.ForeignKey(
        "iam.Role",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="work_items",
        verbose_name=_("assigned to role"),
    )
    assigned_to_unit = models.ForeignKey(
        "organizations.OrganizationNode",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="work_items",
        verbose_name=_("assigned to unit"),
    )

    item_type = models.CharField(
        _("item type"),
        max_length=20,
        choices=WorkboxItemType.choices,
        db_index=True,
    )
    title = models.CharField(_("title"), max_length=500)
    summary = models.CharField(_("summary"), max_length=300, blank=True, default="")
    description = models.TextField(_("description"), blank=True, default="")

    status = models.CharField(
        _("status"),
        max_length=16,
        choices=WorkboxItemStatus.choices,
        default=WorkboxItemStatus.PENDING,
        db_index=True,
    )
    priority = models.CharField(
        _("priority"),
        max_length=10,
        default="medium",
        db_index=True,
    )

    source_type = models.CharField(
        _("source type"),
        max_length=50,
        blank=True,
        default="",
        help_text=_("Semantic source type: assignment, approval, task, ticket, review, custom"),
    )
    source_entity = models.CharField(
        _("source entity"),
        max_length=128,
        help_text=_("e.g. assignments.assignment, approval_engine.request"),
    )
    source_id = models.CharField(
        _("source id"),
        max_length=64,
        help_text=_("public_id or pk of the source item"),
    )
    source_url = models.CharField(
        _("source url"),
        max_length=500,
        blank=True,
        default="",
    )

    due_date     = models.DateTimeField(_("due date"), null=True, blank=True, db_index=True)
    completed_at = models.DateTimeField(_("completed at"), null=True, blank=True)

    is_delegated = models.BooleanField(_("delegated"), default=False, db_index=True)

    metadata = models.JSONField(_("metadata"), default=dict, blank=True)

    class Meta(TenantScopedModel.Meta):
        verbose_name        = _("work item")
        verbose_name_plural = _("work items")
        ordering            = ("-created_at",)
        indexes: ClassVar = [
            *TenantScopedModel.Meta.indexes,
            models.Index(fields=("tenant", "assigned_to_user", "status"), name="wi_tenant_user_status"),
            models.Index(fields=("tenant", "assigned_to_user", "item_type", "status"), name="wi_tenant_user_type_sts"),
            models.Index(fields=("tenant", "assigned_to_user", "due_date"), name="wi_tenant_user_due"),
            models.Index(fields=("tenant", "assigned_to_user", "is_delegated"), name="wi_tenant_user_dlgtd"),
            models.Index(fields=("source_entity", "source_id"), name="wi_source_lookup"),
            models.Index(fields=("tenant", "item_type", "status"), name="wi_tenant_type_status"),
        ]

    def __str__(self) -> str:
        return self.title


class WorkItemTimeline(models.Model):
    """Immutable event log recording every state change on a WorkItem.

    One row per mutation. Never edited after creation. Query by
    ``work_item`` to display inline timeline on the detail view.
    """

    work_item = models.ForeignKey(
        WorkItem,
        on_delete=models.CASCADE,
        related_name="timeline",
        verbose_name=_("work item"),
    )
    event = models.CharField(_("event"), max_length=64)
    from_status = models.CharField(
        _("from status"), max_length=16, blank=True, default=""
    )
    to_status = models.CharField(
        _("to status"), max_length=16, blank=True, default=""
    )
    actor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="work_item_timeline_entries",
        verbose_name=_("actor"),
    )
    note = models.TextField(_("note"), blank=True, default="")
    metadata = models.JSONField(_("metadata"), default=dict, blank=True)
    created_at = models.DateTimeField(_("created at"), auto_now_add=True, db_index=True)

    class Meta:
        verbose_name        = _("work item timeline entry")
        verbose_name_plural = _("work item timeline entries")
        ordering            = ("-created_at",)
        indexes: ClassVar = [
            models.Index(fields=("work_item", "event"), name="wi_timeline_wi_event"),
            models.Index(fields=("work_item", "created_at"), name="wi_timeline_wi_created"),
        ]

    def __str__(self) -> str:
        return f"WorkItem {self.work_item_id} — {self.event}"


# Backward-compatible alias: code that references WorkboxItem gets WorkItem.
WorkboxItem = WorkItem
