"""FRREP-AR010 — growth-area / gap detection for research trend analytics.

``analyse_research_trends`` previously only ever produced ``Kind.CLUSTER``
rows (KMeans + LLM labelling over embeddings). ``Kind.GROWTH_AREA`` and
``Kind.GAP`` existed on the model but nothing populated them. These two are
deterministic, keyword-based signals (no embeddings/LLM required), so they're
tested directly rather than through the full embedding pipeline.
"""

from __future__ import annotations

import itertools
from datetime import timedelta

import pytest
from django.utils import timezone

from apps.repository.analytics.ai_insights import _detect_gaps, _detect_growth_areas
from apps.repository.analytics.models import ResearchTrend
from apps.repository.documents.models import Document, Keyword

_seq = itertools.count(1)


def _published(collection, title, *, published_at=None, **kwargs):
    return Document.objects.create(
        title=title,
        collection=collection,
        status=Document.Status.PUBLISHED,
        visibility=Document.Visibility.PUBLIC_OPEN,
        public_document_id=f"TRD-{next(_seq):05d}",
        published_at=published_at or timezone.now(),
        **kwargs,
    )


def _keyword(label, slug):
    return Keyword.objects.create(
        label=label,
        slug=slug,
        kind=Keyword.Kind.AGROVOC,
        status=Keyword.Status.APPROVED,
    )


@pytest.mark.django_db
def test_detect_growth_areas_flags_keyword_whose_share_doubled(public_collection):
    today = timezone.now().date()
    period_start = today - timedelta(days=30)
    prior_start = period_start - timedelta(days=30)

    kw = _keyword("Drought resilience", "drought-resilience")
    other = _keyword("Soil science", "soil-science")

    # Prior period: 1 drought doc out of 4 total (25% share).
    for i in range(3):
        _published(public_collection, f"prior other {i}", published_at=prior_start + timedelta(days=1)).keywords.add(other)
    _published(public_collection, "prior drought", published_at=prior_start + timedelta(days=1)).keywords.add(kw)

    # Current period: 3 drought docs out of 4 total (75% share) — clear growth.
    for i in range(3):
        _published(public_collection, f"current drought {i}", published_at=period_start + timedelta(days=1)).keywords.add(kw)
    _published(public_collection, "current other", published_at=period_start + timedelta(days=1)).keywords.add(other)

    trends = _detect_growth_areas(period_start, today)

    assert len(trends) == 1
    trend = trends[0]
    assert trend.kind == ResearchTrend.Kind.GROWTH_AREA
    assert "Drought resilience" in trend.title
    assert trend.supporting_documents.count() == 3


@pytest.mark.django_db
def test_detect_growth_areas_ignores_single_document_noise(public_collection):
    today = timezone.now().date()
    period_start = today - timedelta(days=30)

    kw = _keyword("Rare topic", "rare-topic")
    _published(public_collection, "only one", published_at=period_start + timedelta(days=1)).keywords.add(kw)

    trends = _detect_growth_areas(period_start, today)
    assert trends == []


@pytest.mark.django_db
def test_detect_gaps_flags_keyword_far_below_median(public_collection):
    today = timezone.now().date()
    period_start = today - timedelta(days=180)

    # 5 well-represented keywords (10 docs each) + 1 sparse one (1 doc).
    for n in range(5):
        kw = _keyword(f"Topic {n}", f"topic-{n}")
        for i in range(10):
            _published(public_collection, f"doc {n}-{i}").keywords.add(kw)

    sparse = _keyword("Neglected topic", "neglected-topic")
    _published(public_collection, "lone doc").keywords.add(sparse)

    trends = _detect_gaps(period_start, today)

    titles = [t.title for t in trends]
    assert any("Neglected topic" in t for t in titles)
    gap_trend = next(t for t in trends if "Neglected topic" in t.title)
    assert gap_trend.kind == ResearchTrend.Kind.GAP


@pytest.mark.django_db
def test_detect_gaps_requires_minimum_tagged_subjects(public_collection):
    today = timezone.now().date()
    period_start = today - timedelta(days=180)

    # Only 2 tagged subjects — below the 5-subject minimum for a meaningful median.
    for n in range(2):
        kw = _keyword(f"Small corpus topic {n}", f"small-corpus-topic-{n}")
        _published(public_collection, f"doc {n}").keywords.add(kw)

    assert _detect_gaps(period_start, today) == []


@pytest.mark.django_db
def test_analyse_research_trends_runs_growth_and_gap_even_without_embeddings(public_collection, settings):
    """With no embeddings and no OPENAI_API_KEY, cluster trends contribute
    nothing, but growth/gap detection (embedding-independent) should still run."""
    from apps.repository.analytics.ai_insights import analyse_research_trends

    settings.OPENAI_API_KEY = ""

    kw = _keyword("Only topic here", "only-topic-here")
    _published(public_collection, "solo doc").keywords.add(kw)

    # Should not raise even though there's no ResearchTrend data yet / no embeddings.
    trends = analyse_research_trends(period_days=180)
    assert isinstance(trends, list)
