"""Integration tests for app.api.v1.journal_club — queue, archive, decide, AI outline."""

import uuid
import datetime

import pytest
import pytest_asyncio

from app.models.literature import GlobalLiterature
from app.models.team import JournalClubQueue
from app.models.user import Tenant, UserTenant

PMID = 90000930


@pytest_asyncio.fixture
async def auth_ctx(client):
    """Register a user and return (headers, user_id)."""
    email = f"t{uuid.uuid4().hex[:6]}@test.cn"
    resp = await client.post("/api/v1/auth/register", json={
        "email": email, "password": "Test1234", "display_name": "TestUser",
    })
    assert resp.status_code == 200
    data = resp.json()
    headers = {"Authorization": f"Bearer {data['token']['access_token']}"}
    user_id = uuid.UUID(data["user"]["id"])
    return headers, user_id


@pytest_asyncio.fixture
async def seed_lit(db):
    """Seed a literature item. Cleans up first."""
    from sqlalchemy import delete as sql_delete, select
    existing = (await db.execute(select(GlobalLiterature.id).where(GlobalLiterature.pmid == PMID))).scalar()
    if existing:
        await db.execute(sql_delete(JournalClubQueue).where(JournalClubQueue.literature_id == existing))
        await db.execute(sql_delete(GlobalLiterature).where(GlobalLiterature.id == existing))

    lit = GlobalLiterature(
        id=uuid.uuid4(), pmid=PMID, title="Journal Club Test Article",
        abstract="A test article with abstract for journal club discussions.",
        authors=[{"family": "Zhang", "affiliation": "Hospital A"}],
        journal="Nature Medicine", doi="10.1000/nm.001",
        pub_date=datetime.date(2024, 6, 1), pub_year=2024,
    )
    db.add(lit)
    await db.commit()
    return lit


@pytest_asyncio.fixture
async def seed_queue(auth_ctx, db, seed_lit):
    """Create a queued journal club entry."""
    headers, uid = auth_ctx
    from sqlalchemy import select as _select
    r = await db.execute(_select(Tenant.id).join(UserTenant).where(UserTenant.user_id == uid))
    tenant_id = r.scalar()

    # Clean up existing queue items
    from sqlalchemy import delete as sql_delete
    await db.execute(sql_delete(JournalClubQueue).where(JournalClubQueue.tenant_id == tenant_id))

    jc = JournalClubQueue(
        id=uuid.uuid4(), tenant_id=tenant_id, literature_id=seed_lit.id,
        suggested_by=uid, title="Discussion: Test Article", status="queued",
    )
    db.add(jc)
    await db.commit()
    return headers, uid, jc, seed_lit


# ── List Queue ──


@pytest.mark.asyncio
async def test_list_queue_empty(client, auth_ctx):
    """List queue returns empty when none queued."""
    headers, _ = auth_ctx
    r = await client.get("/api/v1/journal-club/queue", headers=headers)
    assert r.status_code == 200
    assert r.json()["items"] == []


@pytest.mark.asyncio
async def test_list_queue_with_items(client, seed_queue):
    """List queue returns queued items."""
    headers, _, jc, lit = seed_queue
    r = await client.get("/api/v1/journal-club/queue", headers=headers)
    assert r.status_code == 200
    data = r.json()
    assert data["total"] == 1
    assert data["items"][0]["pmid"] == PMID
    assert data["items"][0]["status"] == "queued"


# ── Add to Queue ──


@pytest.mark.asyncio
async def test_add_to_queue(client, auth_ctx, seed_lit):
    """Add a literature item to journal club queue."""
    headers, _ = auth_ctx
    r = await client.post("/api/v1/journal-club/queue", headers=headers, json={
        "literature_pmid": PMID, "title": "Interesting Article",
    })
    assert r.status_code == 200
    data = r.json()
    assert data["status"] == "queued"
    assert "id" in data


@pytest.mark.asyncio
async def test_add_to_queue_scheduled(client, auth_ctx, seed_lit):
    """Add with a scheduled date."""
    headers, _ = auth_ctx
    r = await client.post("/api/v1/journal-club/queue", headers=headers, json={
        "literature_pmid": PMID,
        "scheduled_date": "2024-07-15",
    })
    assert r.status_code == 200
    assert r.json()["status"] == "queued"


@pytest.mark.asyncio
async def test_add_to_queue_not_found(client, auth_ctx):
    """Add non-existent PMID returns 404."""
    headers, _ = auth_ctx
    r = await client.post("/api/v1/journal-club/queue", headers=headers, json={
        "literature_pmid": 99999999,
    })
    assert r.status_code == 404


# ── Decide ──


@pytest.mark.asyncio
async def test_decide_presented(client, seed_queue):
    """Decide a queued item as presented."""
    headers, _, jc, _ = seed_queue
    r = await client.post(f"/api/v1/journal-club/queue/{jc.id}/decide",
                          json={"status": "presented", "discussion_notes": "Great discussion"},
                          headers=headers)
    assert r.status_code == 200
    assert r.json()["status"] == "updated"


@pytest.mark.asyncio
async def test_decide_skipped(client, seed_queue):
    """Decide a queued item as skipped."""
    headers, _, jc, _ = seed_queue
    r = await client.post(f"/api/v1/journal-club/queue/{jc.id}/decide",
                          json={"status": "skipped"}, headers=headers)
    assert r.status_code == 200


@pytest.mark.asyncio
async def test_decide_not_found(client, auth_ctx):
    """Decide non-existent item returns 404."""
    headers, _ = auth_ctx
    r = await client.post(f"/api/v1/journal-club/queue/{uuid.uuid4()}/decide",
                          json={"status": "presented"}, headers=headers)
    assert r.status_code == 404


# ── Remove from Queue ──


@pytest.mark.asyncio
async def test_remove_from_queue(client, seed_queue):
    """Remove item from queue."""
    headers, _, jc, _ = seed_queue
    r = await client.delete(f"/api/v1/journal-club/queue/{jc.id}", headers=headers)
    assert r.status_code == 200
    assert r.json()["status"] == "deleted"


@pytest.mark.asyncio
async def test_remove_not_found(client, auth_ctx):
    """Remove non-existent item returns 404."""
    headers, _ = auth_ctx
    r = await client.delete(f"/api/v1/journal-club/queue/{uuid.uuid4()}", headers=headers)
    assert r.status_code == 404


# ── Archive ──


@pytest.mark.asyncio
async def test_list_archive_unavailable(client, auth_ctx):
    """List archive returns 200 with auth (previously lacked auth dependency)."""
    headers, _ = auth_ctx
    r = await client.get("/api/v1/journal-club/archive", headers=headers)
    assert r.status_code in (200, 400)  # 400 if no tenant_ctx, 200 otherwise


@pytest.mark.asyncio
async def test_list_archive_with_items(client, seed_queue):
    """List archive with presented items."""
    headers, _, jc, lit = seed_queue  # noqa: F841
    await client.post(f"/api/v1/journal-club/queue/{jc.id}/decide",
                      json={"status": "presented"}, headers=headers)
    r = await client.get("/api/v1/journal-club/archive", headers=headers)
    assert r.status_code == 200
    data = r.json()
    assert data["total"] >= 1


# ── AI Outline ──


@pytest.mark.asyncio
async def test_generate_outline(client, auth_ctx, seed_lit):
    """Generate AI outline for a literature item."""
    headers, _ = auth_ctx
    r = await client.get(f"/api/v1/journal-club/ai-outline/{PMID}", headers=headers)
    assert r.status_code == 200
    data = r.json()
    assert data["pmid"] == PMID
    assert "outline" in data
    assert "Journal Club" in data["outline"]


@pytest.mark.asyncio
async def test_generate_outline_not_found(client, auth_ctx):
    """Generate outline for non-existent PMID returns 404."""
    headers, _ = auth_ctx
    r = await client.get("/api/v1/journal-club/ai-outline/99999999", headers=headers)
    assert r.status_code == 404


# ── Update Notes ──


@pytest.mark.asyncio
async def test_update_notes(client, seed_queue):
    """Update discussion notes for a queued article."""
    headers, _, jc, _ = seed_queue
    r = await client.post(
        f"/api/v1/journal-club/queue/{jc.id}/notes",
        json={"discussion_notes": "Great paper about targeted therapy showing significant OS benefit."},
        headers=headers,
    )
    assert r.status_code == 200
    data = r.json()
    assert data["status"] == "updated"


@pytest.mark.asyncio
async def test_update_notes_not_found(client, auth_ctx):
    """Update notes for non-existent JID returns 404."""
    headers, _ = auth_ctx
    r = await client.post(
        f"/api/v1/journal-club/queue/{uuid.uuid4()}/notes",
        json={"discussion_notes": "Any notes here."},
        headers=headers,
    )
    assert r.status_code == 404
