"""WS2 UI defects — #20 corrective-action entry point, #41 revision diff, #49 403 page."""
from __future__ import annotations

from datetime import date, timedelta

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

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

_N = {"n": 0}


def _activity_row():
    _N["n"] += 1
    lf = LogFrame.objects.create(name=f"LF-{_N['n']}", slug=f"lf-ui-{_N['n']}")
    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)


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


@pytest.fixture
def delayed_activity():
    return Activity.objects.create(
        logframe_row=_activity_row(), name="Field training",
        scheduled_start=date.today() - timedelta(days=30),
        scheduled_end=date.today() - timedelta(days=5),
        status=ActivityStatus.DELAYED, deviation_flag=True,
    )


# --- #20 -----------------------------------------------------------------


def test_activity_detail_has_corrective_action_entry(client, officer, delayed_activity):
    client.force_login(officer)
    resp = client.get(reverse("mel_tracking:activity_detail", kwargs={"pk": delayed_activity.pk}))
    assert resp.status_code == 200
    body = resp.content
    assert b"Create corrective action" in body
    assert b"subject_app=mel_tracking" in body
    assert b"subject_model=activity" in body


def test_corrective_action_create_accepts_activity_subject(client, officer, delayed_activity):
    client.force_login(officer)
    url = (
        reverse("mel_tracking:corrective_action_create")
        + f"?subject_app=mel_tracking&subject_model=activity&subject_id={delayed_activity.pk}"
    )
    resp = client.get(url)
    assert resp.status_code == 200
    assert resp.context["subject"].pk == delayed_activity.pk


# --- #41 -----------------------------------------------------------------


def test_activity_history_shows_field_diff(client, officer, delayed_activity):
    # Produce an UPDATE revision so diff_against has something to compare.
    delayed_activity.name = "Field training (rescheduled)"
    delayed_activity.save()

    client.force_login(officer)
    resp = client.get(reverse("mel_tracking:activity_history", kwargs={"pk": delayed_activity.pk}))
    assert resp.status_code == 200
    # The update row carries a name change old → new.
    update_rows = [r for r in resp.context["history_rows"] if r["changes"]]
    assert update_rows, "expected at least one revision with a computed diff"
    name_changes = [c for row in update_rows for c in row["changes"] if c["field"] == "name"]
    assert name_changes
    assert name_changes[0]["old"] == "Field training"
    assert name_changes[0]["new"] == "Field training (rescheduled)"
    assert b"Field training (rescheduled)" in resp.content


# --- #49 -----------------------------------------------------------------


def test_403_page_hides_signin_for_authenticated_user(client):
    learner = User.objects.create_user(email="ws2ui-learner@example.com", password="x", role=UserRole.LEARNER)
    client.force_login(learner)
    resp = client.get(reverse("mel_tracking:tracking_dashboard"))
    assert resp.status_code == 403
    assert b"Go to dashboard" in resp.content
    assert b"Sign in" not in resp.content
