"""AI audit trail: suggestions, action invocations, approvals.

Three tables:

* :class:`AISuggestion` — anything an agent or action produced that
  awaits review (or was auto-applied with full provenance).
* :class:`AIActionLog` — every executed action with payload + status.
* :class:`AIApproval` — approval/rejection events linked to a suggestion.

All tenant-scoped via :class:`TenantScopedModel`. The unique constraint on
:class:`AIApproval` (one approval per (suggestion, actor)) prevents
duplicate votes.
"""

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 TenantScopedModel, UUIDModel


class SuggestionStatus(models.TextChoices):
    PENDING = "pending", _("Pending")
    APPROVED = "approved", _("Approved")
    REJECTED = "rejected", _("Rejected")
    APPLIED = "applied", _("Applied")
    DISMISSED = "dismissed", _("Dismissed")


class SuggestionKind(models.TextChoices):
    ACTION = "action", _("Action proposal")
    INSIGHT = "insight", _("Insight")
    AGENT_OUTPUT = "agent_output", _("Agent output")


class AISuggestion(UUIDModel, TenantScopedModel):
    kind = models.CharField(
        _("kind"),
        max_length=20,
        choices=SuggestionKind.choices,
        default=SuggestionKind.AGENT_OUTPUT,
    )
    status = models.CharField(
        _("status"),
        max_length=12,
        choices=SuggestionStatus.choices,
        default=SuggestionStatus.PENDING,
    )
    title = models.CharField(_("title"), max_length=200)
    summary = models.TextField(_("summary"), blank=True, default="")
    # Provenance: which agent/prompt/action produced it.
    source = models.CharField(_("source"), max_length=120, blank=True, default="")
    # Optional proposed action + payload (used when kind=ACTION).
    proposed_action = models.CharField(
        _("proposed action"),
        max_length=120,
        blank=True,
        default="",
    )
    payload = models.JSONField(_("payload"), default=dict, blank=True)
    metadata = models.JSONField(_("metadata"), default=dict, blank=True)
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name="+",
        null=True,
        blank=True,
    )

    class Meta:
        verbose_name = _("AI suggestion")
        verbose_name_plural = _("AI suggestions")
        ordering = ("-created_at",)
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "status")),
            models.Index(fields=("tenant", "kind", "status")),
        ]

    def __str__(self) -> str:
        return f"{self.kind}:{self.title} [{self.status}]"


class ActionLogStatus(models.TextChoices):
    SUCCEEDED = "succeeded", _("Succeeded")
    FAILED = "failed", _("Failed")
    REJECTED = "rejected", _("Rejected (validation)")
    PENDING_APPROVAL = "pending_approval", _("Pending approval")


class AIActionLog(UUIDModel, TenantScopedModel):
    action_key = models.CharField(_("action"), max_length=120)
    status = models.CharField(
        _("status"),
        max_length=20,
        choices=ActionLogStatus.choices,
    )
    payload = models.JSONField(_("payload"), default=dict, blank=True)
    result = models.JSONField(_("result"), default=dict, blank=True)
    error = models.TextField(_("error"), blank=True, default="")
    actor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name="+",
        null=True,
        blank=True,
    )
    suggestion = models.ForeignKey(
        AISuggestion,
        on_delete=models.SET_NULL,
        related_name="action_logs",
        null=True,
        blank=True,
    )

    class Meta:
        verbose_name = _("AI action log")
        verbose_name_plural = _("AI action logs")
        ordering = ("-created_at",)
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "action_key")),
            models.Index(fields=("tenant", "status")),
        ]

    def __str__(self) -> str:
        return f"{self.action_key} [{self.status}]"


class ApprovalDecision(models.TextChoices):
    APPROVE = "approve", _("Approve")
    REJECT = "reject", _("Reject")


class AIApproval(UUIDModel, TenantScopedModel):
    suggestion = models.ForeignKey(
        AISuggestion,
        on_delete=models.CASCADE,
        related_name="approvals",
    )
    actor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        related_name="+",
        null=True,
        blank=True,
    )
    decision = models.CharField(
        _("decision"),
        max_length=10,
        choices=ApprovalDecision.choices,
    )
    note = models.TextField(_("note"), blank=True, default="")

    class Meta:
        verbose_name = _("AI approval")
        verbose_name_plural = _("AI approvals")
        ordering = ("-created_at",)
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("suggestion", "actor"),
                name="ai_approval_unique_actor_per_suggestion",
            ),
        ]
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "decision")),
        ]

    def __str__(self) -> str:
        return f"{self.decision}@{self.suggestion_id}"
