import pytest
import datetime
from django.urls import reverse
from django.contrib.auth import get_user_model
from django.test import Client
from atlas.models import CaseCollection, Case, CasePrior, CaseDetail

@pytest.mark.django_db
def test_case_future_priors_chain(make_case):
    # Create a chain of cases: case1 -> case2 -> case3
    case1 = make_case(title="Case 1")
    case2 = make_case(title="Case 2")
    case3 = make_case(title="Case 3")

    case2.previous_case = case1
    case2.save(update_fields=["previous_case"])

    case3.previous_case = case2
    case3.save(update_fields=["previous_case"])

    # Test get_all_prior_cases
    assert case1.get_all_prior_cases() == []
    assert case2.get_all_prior_cases() == [case1]
    assert case3.get_all_prior_cases() == [case2, case1]

    # Test get_all_future_cases
    assert case1.get_all_future_cases() == [case2, case3]
    assert case2.get_all_future_cases() == [case3]
    assert case3.get_all_future_cases() == []


@pytest.mark.django_db
def test_case_prior_and_future_relation_post(client, make_case):
    # Setup user and collection
    user = get_user_model().objects.create_user(
        username="author_user", password="password", email="author@test.com"
    )
    collection = CaseCollection.objects.create(name="Test Prior Future Collection")
    collection.author.add(user)

    case1 = make_case(title="Case 1")
    case2 = make_case(title="Case 2")
    case3 = make_case(title="Case 3")

    case2.previous_case = case1
    case2.save(update_fields=["previous_case"])

    case3.previous_case = case2
    case3.save(update_fields=["previous_case"])

    # Add case2 (the index case) to the collection
    casedetail = CaseDetail.objects.create(case=case2, collection=collection)

    client.force_login(user)

    # 1. Post to link case1 (should be auto-detected as a PRIOR relation)
    url = reverse(
        "atlas:collection_case_priors",
        kwargs={"exam_id": collection.pk, "case_number": 0},
    )
    response = client.post(
        url,
        data={
            "prior_case_id": case1.pk,
            "relation": "Baseline exam",
            "prior_visibility": "AL",
        },
        HTTP_HX_REQUEST="true",
    )
    assert response.status_code == 200
    assert "Baseline exam" in response.content.decode("utf-8")
    assert "Prior" in response.content.decode("utf-8")

    # Verify in DB
    p1 = CasePrior.objects.get(casedetail=casedetail, prior_case=case1)
    assert p1.relation_type == CasePrior.RelationType.PRIOR
    assert p1.relation_text == "Baseline exam"

    # 2. Post to link case3 (should be auto-detected as a FUTURE relation)
    response = client.post(
        url,
        data={
            "prior_case_id": case3.pk,
            "relation": "Follow-up exam",
            "prior_visibility": "AL",
        },
        HTTP_HX_REQUEST="true",
    )
    assert response.status_code == 200
    assert "Follow-up exam" in response.content.decode("utf-8")
    assert "Future" in response.content.decode("utf-8")

    # Verify in DB
    p3 = CasePrior.objects.get(casedetail=casedetail, prior_case=case3)
    assert p3.relation_type == CasePrior.RelationType.FUTURE
    assert p3.relation_text == "Follow-up exam"

    # Verify GET returns both sections and shows the related cases
    response_get = client.get(url)
    assert response_get.status_code == 200
    content = response_get.content.decode("utf-8")
    assert "Available Prior Exams" in content
    assert "Available Future Exams" in content
    assert "Baseline exam" in content
    assert "Follow-up exam" in content

    # Test named stacks JSON payload
    stacks_json = casedetail.get_case_named_stacks()
    assert "Prior: Baseline exam" in stacks_json
    assert "Future: Follow-up exam" in stacks_json

    # Test DICOM JSON endpoint
    dicom_url = reverse(
        "atlas:collection_case_dicom_json",
        kwargs={"exam_id": collection.pk, "case_number": 0},
    )
    response_dicom = client.get(dicom_url)
    assert response_dicom.status_code == 200
    dicom_data = response_dicom.json()
    descriptions = [study.get("StudyDescription") for study in dicom_data["studies"] if "StudyDescription" in study]
    assert "Prior: Baseline exam" in descriptions
    assert "Future: Follow-up exam" in descriptions

    # 3. Post to remove case3
    response_remove = client.post(
        url,
        data={
            "remove": case3.pk,
        },
        HTTP_HX_REQUEST="true",
    )
    assert response_remove.status_code == 200
    assert not CasePrior.objects.filter(casedetail=casedetail, prior_case=case3).exists()


@pytest.mark.django_db
def test_linked_cases_reordering(client, make_case):
    # Setup user
    user = get_user_model().objects.create_user(
        username="author_user_reorder", password="password", email="author_reorder@test.com"
    )
    
    case1 = make_case(title="Case A")
    case2 = make_case(title="Case B")
    case3 = make_case(title="Case C")

    # Author permissions
    case1.author.add(user)
    case2.author.add(user)
    case3.author.add(user)

    # Initial order: case1 -> case2 -> case3
    case2.previous_case = case1
    case2.save(update_fields=["previous_case"])
    case3.previous_case = case2
    case3.save(update_fields=["previous_case"])

    client.force_login(user)
    url = reverse("atlas:linked_cases_overview", kwargs={"case_id": case2.pk})

    # Verify GET works and shows reorder editor when requested
    response_get = client.get(url + "?show_reorder=1")
    assert response_get.status_code == 200
    assert "Reorder Cases" in response_get.content.decode("utf-8")

    # Post new order: case3 -> case1 -> case2
    response_post = client.post(
        url,
        data={
            "form_action": "reorder_cases",
            "case_order_0": case3.pk,
            "case_order_1": case1.pk,
            "case_order_2": case2.pk,
        },
        follow=True,
    )
    assert response_post.status_code == 200

    # Refresh cases from database
    case1.refresh_from_db()
    case2.refresh_from_db()
    case3.refresh_from_db()

    # Verify new order in DB: case3 -> case1 -> case2
    assert case3.previous_case is None
    assert case1.previous_case == case3
    assert case2.previous_case == case1

