"""Analytics + AI insight models for the Repository (PRD REPO-SP9)."""

from __future__ import annotations

from django.conf import settings
from django.db import models

try:  # pgvector only available when the package is installed in the environment.
    from pgvector.django import HnswIndex, VectorField
    _PGVECTOR_AVAILABLE = True
except ImportError:  # pragma: no cover
    _PGVECTOR_AVAILABLE = False
    VectorField = None  # type: ignore[assignment]
    HnswIndex = None  # type: ignore[assignment]


# ── Event sources ──────────────────────────────────────────────────────────


class AccessEvent(models.Model):
    class Source(models.TextChoices):
        DIRECT = "direct", "Direct"
        # FRREP-INT006 — an access that arrived via a REP lesson's OER link,
        # routed through OERAccessRedirectView so REP-driven reach is
        # distinguishable from direct Repository browsing.
        REP = "rep", "REP lesson"

    document = models.ForeignKey(
        "repository_documents.Document",
        on_delete=models.CASCADE,
        related_name="access_events",
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="repository_access_events",
    )
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    user_agent = models.CharField(max_length=512, blank=True)
    country = models.CharField(max_length=100, blank=True)
    referrer = models.CharField(max_length=500, blank=True)
    source = models.CharField(
        max_length=16, choices=Source.choices, default=Source.DIRECT, db_index=True
    )
    timestamp = models.DateTimeField(auto_now_add=True, db_index=True)

    class Meta:
        ordering = ["-timestamp"]
        indexes = [models.Index(fields=["document", "timestamp"])]


class DownloadEvent(models.Model):
    document = models.ForeignKey(
        "repository_documents.Document",
        on_delete=models.CASCADE,
        related_name="download_events",
    )
    version = models.ForeignKey(
        "repository_documents.DocumentVersion",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="download_events",
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="repository_download_events",
    )
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    country = models.CharField(max_length=100, blank=True)
    timestamp = models.DateTimeField(auto_now_add=True, db_index=True)

    class Meta:
        ordering = ["-timestamp"]
        indexes = [models.Index(fields=["document", "timestamp"])]


class SearchEvent(models.Model):
    query = models.TextField(blank=True)
    filters = models.JSONField(default=dict, blank=True)
    result_count = models.PositiveIntegerField(default=0)
    clicked_document = models.ForeignKey(
        "repository_documents.Document",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="search_clicks",
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="repository_search_events",
    )
    timestamp = models.DateTimeField(auto_now_add=True, db_index=True)

    class Meta:
        ordering = ["-timestamp"]


# ── Rollups / reports ──────────────────────────────────────────────────────


class UsageRollup(models.Model):
    class Dimension(models.TextChoices):
        COLLECTION = "collection", "Collection"
        DOCUMENT_TYPE = "document_type", "Document type"
        COUNTRY = "country", "Country"
        AUTHOR = "author", "Author"
        OVERALL = "overall", "Overall"

    period_start = models.DateField()
    period_end = models.DateField()
    dimension = models.CharField(max_length=24, choices=Dimension.choices)
    key = models.CharField(max_length=160, blank=True)
    metrics = models.JSONField(default=dict, blank=True)
    computed_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ["-period_end", "dimension"]
        constraints = [
            models.UniqueConstraint(
                fields=["period_start", "period_end", "dimension", "key"],
                name="uniq_usage_rollup_period",
            ),
        ]


# ── AI insights (REPO-SP9) ─────────────────────────────────────────────────


class AIDocumentInsight(models.Model):
    class Kind(models.TextChoices):
        SUMMARY = "summary", "Summary"
        CLASSIFICATION = "classification", "Classification"
        METADATA = "metadata", "Metadata extraction"

    document = models.ForeignKey(
        "repository_documents.Document",
        on_delete=models.CASCADE,
        related_name="ai_insights",
    )
    kind = models.CharField(max_length=24, choices=Kind.choices, db_index=True)
    payload = models.JSONField(default=dict)
    confidence = models.FloatField(null=True, blank=True)
    model_used = models.CharField(max_length=64, blank=True)
    generated_at = models.DateTimeField(auto_now_add=True)
    accepted_by_user = models.BooleanField(null=True, blank=True)

    class Meta:
        ordering = ["-generated_at"]
        indexes = [models.Index(fields=["document", "kind"])]


if _PGVECTOR_AVAILABLE:

    class DocumentEmbedding(models.Model):
        document = models.ForeignKey(
            "repository_documents.Document",
            on_delete=models.CASCADE,
            related_name="embeddings",
        )
        chunk_index = models.PositiveIntegerField(default=0)
        chunk_text = models.TextField(blank=True)
        embedding = VectorField(dimensions=1536)
        metadata = models.JSONField(default=dict, blank=True)
        created_at = models.DateTimeField(auto_now_add=True)

        class Meta:
            ordering = ["document", "chunk_index"]
            indexes = [
                HnswIndex(
                    name="repo_doc_embedding_hnsw",
                    fields=["embedding"],
                    m=16,
                    ef_construction=64,
                    opclasses=["vector_cosine_ops"],
                ),
            ]
            constraints = [
                models.UniqueConstraint(
                    fields=["document", "chunk_index"],
                    name="uniq_document_embedding_chunk",
                ),
            ]

else:  # pragma: no cover — degraded mode (pgvector not installed).

    class DocumentEmbedding(models.Model):
        document = models.ForeignKey(
            "repository_documents.Document",
            on_delete=models.CASCADE,
            related_name="embeddings",
        )
        chunk_index = models.PositiveIntegerField(default=0)
        chunk_text = models.TextField(blank=True)
        embedding_raw = models.JSONField(default=list)
        metadata = models.JSONField(default=dict, blank=True)
        created_at = models.DateTimeField(auto_now_add=True)

        class Meta:
            ordering = ["document", "chunk_index"]


class ResearchTrend(models.Model):
    class Kind(models.TextChoices):
        CLUSTER = "cluster", "Cluster"
        GROWTH_AREA = "growth_area", "Growth area"
        GAP = "gap", "Gap"

    period_start = models.DateField()
    period_end = models.DateField()
    kind = models.CharField(max_length=16, choices=Kind.choices, db_index=True)
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    supporting_documents = models.ManyToManyField(
        "repository_documents.Document",
        blank=True,
        related_name="supporting_trends",
    )
    score = models.FloatField(default=0.0)
    generated_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-generated_at", "-score"]
