"""Content Engine domain models.

Model inventory
---------------
ContentCategory   — hierarchical category tree for content items.
ContentItem       — unified content entity (14 content types).
ContentVersion    — immutable snapshot on publish.

Design decisions
----------------
* Every business entity extends TenantScopedModel (tenant + org_node FKs).
* UUIDModel exposes public_id for external identifiers.
* AuditedModel adds created_by/updated_by auto-populated from RequestContext.
* SoftDeleteModel protects content from accidental hard-delete.
* VersionedModel provides optimistic concurrency control.
* ContentItem.content_type is a TextChoices discriminator — NOT separate tables.
* Attachments, Comments, Tags, Custom Fields: reuse platform_core (GenericFK).
* Workflow: ContentItem.workflow_instance FK to WorkflowInstance.
* Approval: via Approval Engine (ApprovalRequest linked to ContentItem).
"""

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,
    OrderedModel,
    ScopedSoftDeleteManager,
    SoftDeleteModel,
    TenantScopedModel,
    UUIDModel,
    VersionedModel,
)


class ContentType(models.TextChoices):
    DEV_DOC       = "dev_doc",       _("Developer Documentation")
    USER_MANUAL   = "user_manual",   _("User Manual")
    ADMIN_MANUAL  = "admin_manual",  _("Admin Manual")
    ARCH_DOC      = "arch_doc",      _("Architecture Documentation")
    API_DOC       = "api_doc",       _("API Documentation")
    KB_ARTICLE    = "kb_article",    _("Knowledge Base Article")
    FAQ           = "faq",           _("FAQ")
    PROCEDURE     = "procedure",     _("Procedure")
    POLICY        = "policy",        _("Policy")
    ARTICLE       = "article",       _("Article")
    NEWS          = "news",          _("News")
    ANNOUNCEMENT  = "announcement",  _("Announcement")
    RELEASE_NOTES = "release_notes", _("Release Notes")
    CHANGELOG     = "changelog",     _("Changelog")


class ContentVisibility(models.TextChoices):
    PUBLIC   = "public",   _("Public")
    INTERNAL = "internal", _("Internal — authenticated users")
    PRIVATE  = "private",  _("Private — author only")


class ContentStatus(models.TextChoices):
    DRAFT     = "draft",     _("Draft")
    REVIEW    = "review",    _("In Review")
    APPROVED  = "approved",  _("Approved")
    PUBLISHED = "published", _("Published")
    ARCHIVED  = "archived",  _("Archived")


# ---------------------------------------------------------------------------
# ContentCategory
# ---------------------------------------------------------------------------

class ContentCategory(UUIDModel, TenantScopedModel, OrderedModel):
    """Hierarchical category tree for content items."""

    parent = models.ForeignKey(
        "self",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="children",
        verbose_name=_("parent category"),
    )
    name = models.CharField(_("name"), max_length=200)
    slug = models.SlugField(_("slug"), max_length=200)
    description = models.TextField(_("description"), blank=True, default="")
    icon = models.CharField(_("icon"), max_length=50, blank=True, default="")
    is_active = models.BooleanField(_("active"), default=True, db_index=True)

    class Meta:
        verbose_name = _("content category")
        verbose_name_plural = _("content categories")
        unique_together = [("tenant", "slug")]
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "parent")),
            models.Index(fields=("tenant", "is_active")),
        ]

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


# ---------------------------------------------------------------------------
# ContentItem
# ---------------------------------------------------------------------------

class ContentItem(UUIDModel, TenantScopedModel, AuditedModel, SoftDeleteModel, VersionedModel):
    """Unified content model — all content types in one table."""

    title = models.CharField(_("title"), max_length=500)
    slug = models.SlugField(_("slug"), max_length=500)
    content_type = models.CharField(
        _("content type"),
        max_length=30,
        choices=ContentType.choices,
        db_index=True,
    )
    category = models.ForeignKey(
        ContentCategory,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="items",
        verbose_name=_("category"),
    )
    body = models.TextField(_("body"), blank=True, default="")
    excerpt = models.TextField(_("excerpt"), blank=True, default="", max_length=2000)
    status = models.CharField(
        _("status"),
        max_length=20,
        choices=ContentStatus.choices,
        default=ContentStatus.DRAFT,
        db_index=True,
    )
    visibility = models.CharField(
        _("visibility"),
        max_length=12,
        choices=ContentVisibility.choices,
        default=ContentVisibility.INTERNAL,
    )
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT,
        related_name="authored_content",
        verbose_name=_("author"),
    )
    published_at = models.DateTimeField(_("published at"), null=True, blank=True, db_index=True)
    archived_at = models.DateTimeField(_("archived at"), null=True, blank=True)

    # SEO / metadata
    meta_title = models.CharField(_("meta title"), max_length=200, blank=True, default="")
    meta_description = models.TextField(_("meta description"), blank=True, default="", max_length=500)
    meta_keywords = models.CharField(_("meta keywords"), max_length=500, blank=True, default="")

    # Denormalized counters (updated via F() expressions)
    view_count = models.PositiveIntegerField(_("view count"), default=0)
    helpful_count = models.PositiveIntegerField(_("helpful count"), default=0)
    not_helpful_count = models.PositiveIntegerField(_("not helpful count"), default=0)

    # AI / Semantic metadata
    ai_description = models.TextField(_("AI description"), blank=True, default="")
    ai_semantic_type = models.CharField(_("AI semantic type"), max_length=100, blank=True, default="")
    ai_summary = models.TextField(_("AI summary"), blank=True, default="")

    # Related content (soft refs — JSON array of public_id UUIDs)
    related_content = models.JSONField(_("related content"), default=list, blank=True)

    # Workflow instance link
    workflow_instance = models.ForeignKey(
        "platform_workflow.WorkflowInstance",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
        verbose_name=_("workflow instance"),
    )

    # Workspace context (nullable — workspace-scoped content)
    workspace = models.ForeignKey(
        "platform_workspaces.Workspace",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="content_items",
        verbose_name=_("workspace"),
    )

    objects = ScopedSoftDeleteManager()

    class Meta:
        verbose_name = _("content item")
        verbose_name_plural = _("content items")
        unique_together = [("tenant", "slug")]
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "content_type")),
            models.Index(fields=("tenant", "status")),
            models.Index(fields=("tenant", "category")),
            models.Index(fields=("tenant", "author")),
            models.Index(fields=("tenant", "published_at")),
            models.Index(fields=("tenant", "content_type", "status")),
            models.Index(fields=("tenant", "visibility")),
        ]
        ordering = ["-published_at", "-created_at"]

    def __str__(self) -> str:
        return f"{self.get_content_type_display()}: {self.title} [{self.status}]"


# ---------------------------------------------------------------------------
# ContentVersion
# ---------------------------------------------------------------------------

class ContentVersion(UUIDModel, TenantScopedModel):
    """Immutable snapshot of content at publish time."""

    content_item = models.ForeignKey(
        ContentItem,
        on_delete=models.CASCADE,
        related_name="versions",
        verbose_name=_("content item"),
    )
    version = models.PositiveIntegerField(_("version number"))
    title = models.CharField(_("title"), max_length=500)
    body = models.TextField(_("body"))
    excerpt = models.TextField(_("excerpt"), blank=True, default="", max_length=2000)
    status = models.CharField(_("status at snapshot"), max_length=20, choices=ContentStatus.choices)
    changed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
        verbose_name=_("changed by"),
    )
    change_summary = models.CharField(_("change summary"), max_length=500, blank=True, default="")
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)

    class Meta:
        verbose_name = _("content version")
        verbose_name_plural = _("content versions")
        unique_together = [("content_item", "version")]
        ordering = ["-version"]

    def __str__(self) -> str:
        return f"{self.content_item_id} v{self.version}"
