"""Recent-preview panels capped at 5, with full "View all" pages.

- Dashboard "Recent cross-module activity" + participants preview cap at 5.
- Activity / output "Recent revisions" cap at 5 on the detail page, with a full
  history page (ActivityHistoryView / OutputDeliverableHistoryView) listing all.
- MilestoneListView is the full cross-module activity feed (paginated at 10).
"""
from __future__ import annotations

from datetime import date

import pytest
from django.contrib.auth import get_user_model
from django.urls import reverse

from apps.core.permissions.roles import UserRole
from apps.mel.indicators.models import LogFrame, LogFrameLevel, LogFrameRow
from apps.mel.tracking.models import (
    Activity,
    ActivityStatus,
    OutputDeliverable,
    Participant,
    TrackingRecord,
)
from apps.mel.tracking.services import ensure_participant, record_event

User = get_user_model()
pytestmark = pytest.mark.django_db


@pytest.fixture
def officer():
    return User.objects.create_user(
        email="preview-officer@example.com", password="x", role=UserRole.MEL_OFFICER,
    )


def _activity_row():
    lf = LogFrame.objects.create(name="LF-prev", slug="lf-prev-act")
    impact = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.IMPACT, title="I")
    outcome = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.OUTCOME, title="O", parent=impact)
    output = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.OUTPUT, title="P", parent=outcome)
    return LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.ACTIVITY, title="A", parent=output), output


# ---------------------------------------------------------------------------
# MilestoneListView — full cross-module activity feed
# ---------------------------------------------------------------------------

def _make_milestones(user, module, n, start=0):
    for i in range(n):
        record_event(
            user=user,
            source_module=module,
            event_type="award_created" if module == TrackingRecord.Module.RIMS else "course_completed",
            source_id=start + i,
            label=f"{module}-evt-{start + i}",
        )


def test_event_log_and_milestones_feed_coexist(client, officer):
    """The Upstream event log lives at /mel/events/; the cross-module activity
    feed (dashboard 'View all' target) lives at /mel/events/milestones/."""
    client.force_login(officer)
    assert reverse("mel_tracking:event_log") == "/mel/events/"
    assert reverse("mel_tracking:milestone_list") == "/mel/events/milestones/"
    assert client.get("/mel/events/", HTTP_HOST="localhost").status_code == 200
    assert client.get("/mel/events/milestones/", HTTP_HOST="localhost").status_code == 200


def test_milestone_list_paginates_at_10(client, officer):
    learner = User.objects.create_user(email="ms-learner@example.com", password="x", role=UserRole.LEARNER)
    _make_milestones(learner, TrackingRecord.Module.RIMS, 12)

    client.force_login(officer)
    resp = client.get(reverse("mel_tracking:milestone_list"), HTTP_HOST="localhost")
    assert resp.status_code == 200
    page = resp.context["page_obj"]
    assert page.paginator.count == 12
    assert page.paginator.num_pages == 2
    assert len(page.object_list) == 10


def test_milestone_list_filters_by_module(client, officer):
    learner = User.objects.create_user(email="ms-learner2@example.com", password="x", role=UserRole.LEARNER)
    _make_milestones(learner, TrackingRecord.Module.RIMS, 3, start=0)
    _make_milestones(learner, TrackingRecord.Module.REP, 2, start=100)

    client.force_login(officer)
    resp = client.get(reverse("mel_tracking:milestone_list"), {"module": "rep"}, HTTP_HOST="localhost")
    assert resp.status_code == 200
    assert resp.context["page_obj"].paginator.count == 2


# ---------------------------------------------------------------------------
# Activity / output revisions — detail caps at 5, history page lists all
# ---------------------------------------------------------------------------

def test_activity_detail_caps_history_and_full_page_lists_all(client, officer):
    row, _output = _activity_row()
    activity = Activity.objects.create(
        logframe_row=row, name="Q1 sweep",
        scheduled_start=date(2026, 1, 1), scheduled_end=date(2026, 2, 1),
    )
    for i in range(7):  # 7 edits → 8 history rows (1 create + 7 updates)
        activity.name = f"Q1 sweep v{i}"
        activity.save()

    client.force_login(officer)
    detail = client.get(reverse("mel_tracking:activity_detail", kwargs={"pk": activity.pk}), HTTP_HOST="localhost")
    assert detail.status_code == 200
    assert len(detail.context["history"]) == 5

    full = client.get(reverse("mel_tracking:activity_history", kwargs={"pk": activity.pk}), HTTP_HOST="localhost")
    assert full.status_code == 200
    assert full.context["history_records"].count() == 8


def test_output_history_view_lists_all(client, officer):
    _row, output_row = _activity_row()
    deliverable = OutputDeliverable.objects.create(
        logframe_row=output_row, title="Reports", target_quantity=10, unit="reports",
    )
    for i in range(6):
        deliverable.title = f"Reports v{i}"
        deliverable.save()

    client.force_login(officer)
    detail = client.get(reverse("mel_tracking:output_detail", kwargs={"pk": deliverable.pk}), HTTP_HOST="localhost")
    assert detail.status_code == 200
    assert len(detail.context["history"]) == 5

    full = client.get(reverse("mel_tracking:output_history", kwargs={"pk": deliverable.pk}), HTTP_HOST="localhost")
    assert full.status_code == 200
    assert full.context["history_records"].count() == 7


# ---------------------------------------------------------------------------
# Dashboard previews capped at 5
# ---------------------------------------------------------------------------

def test_dashboard_recent_previews_capped_at_5(client, officer):
    for i in range(7):
        u = User.objects.create_user(email=f"dash-prev-{i}@example.com", password="x", role=UserRole.LEARNER)
        ensure_participant(u)
        record_event(
            user=u, source_module=TrackingRecord.Module.RIMS,
            event_type="award_created", source_id=i, label=f"evt-{i}",
        )

    client.force_login(officer)
    resp = client.get(reverse("mel_tracking:tracking_dashboard"), HTTP_HOST="localhost")
    assert resp.status_code == 200
    assert len(resp.context["recent_milestones"]) <= 5
    assert len(resp.context["participants_preview"]) <= 5
