"""Integration tests for app.api.v1.highlights — CRUD for PDF highlights."""

import uuid
import datetime

import pytest
import pytest_asyncio

from app.models.interaction import UserPdfHighlight
from app.models.literature import GlobalLiterature

PMID = 90000920


@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
    lit = (await db.execute(select(GlobalLiterature.id).where(GlobalLiterature.pmid == PMID))).scalar()
    if lit:
        await db.execute(sql_delete(UserPdfHighlight).where(UserPdfHighlight.literature_id == lit))
        await db.execute(sql_delete(GlobalLiterature).where(GlobalLiterature.id == lit))

    lit = GlobalLiterature(
        id=uuid.uuid4(), pmid=PMID, title="Highlight Test Article",
        abstract="Testing highlights", authors=[{"family": "Wang"}],
        journal="Test Journal", doi="10.1000/test.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_highlight(auth_ctx, db, seed_lit):
    """Create a highlight for the user on the seeded literature."""
    headers, uid = auth_ctx
    h = UserPdfHighlight(
        id=uuid.uuid4(), user_id=uid, literature_id=seed_lit.id,
        highlight_type="highlight", page_number=1, position={},
        text="Important passage", color="#ffff00",
    )
    db.add(h)
    await db.commit()
    return headers, uid, h, seed_lit


# ── List Highlights ──


@pytest.mark.asyncio
async def test_list_highlights_empty(client, auth_ctx, seed_lit):
    """List highlights returns empty when none created."""
    headers, _ = auth_ctx
    r = await client.get(f"/api/v1/highlights/{PMID}", headers=headers)
    assert r.status_code == 200
    assert r.json() == []


@pytest.mark.asyncio
async def test_list_highlights_with_data(client, seed_highlight):
    """List highlights returns created highlight."""
    headers, _, h, _ = seed_highlight
    r = await client.get(f"/api/v1/highlights/{PMID}", headers=headers)
    assert r.status_code == 200
    data = r.json()
    assert len(data) == 1
    assert data[0]["type"] == "highlight"
    assert data[0]["page"] == 1
    assert data[0]["text"] == "Important passage"
    assert data[0]["color"] == "#ffff00"


@pytest.mark.asyncio
async def test_list_highlights_lit_not_found(client, auth_ctx):
    """List highlights for non-existent PMID returns 404."""
    headers, _ = auth_ctx
    r = await client.get("/api/v1/highlights/99999999", headers=headers)
    assert r.status_code == 404


# ── Create Highlight ──


@pytest.mark.asyncio
async def test_create_highlight(client, auth_ctx, seed_lit):
    """Create a highlight."""
    headers, _ = auth_ctx
    r = await client.post(f"/api/v1/highlights/{PMID}", headers=headers, json={
        "highlight_type": "underline", "page_number": 2,
        "text": "Underlined text", "color": "#00ff00",
    })
    assert r.status_code == 200
    data = r.json()
    assert data["status"] == "created"
    assert "id" in data

    # Verify it appears in list
    r2 = await client.get(f"/api/v1/highlights/{PMID}", headers=headers)
    assert len(r2.json()) == 1


@pytest.mark.asyncio
async def test_create_highlight_with_note(client, auth_ctx, seed_lit):
    """Create a highlight with a note."""
    headers, _ = auth_ctx
    r = await client.post(f"/api/v1/highlights/{PMID}", headers=headers, json={
        "highlight_type": "highlight", "page_number": 1,
        "text": "Notable passage", "note": "This is important",
        "color": "#ff0000",
    })
    assert r.status_code == 200
    data = r.json()
    assert data["status"] == "created"

    r2 = await client.get(f"/api/v1/highlights/{PMID}", headers=headers)
    hl = r2.json()[0]
    assert hl["note"] == "This is important"


@pytest.mark.asyncio
async def test_create_highlight_lit_not_found(client, auth_ctx):
    """Create highlight for non-existent PMID returns 404."""
    headers, _ = auth_ctx
    r = await client.post("/api/v1/highlights/99999999", headers=headers, json={
        "highlight_type": "highlight", "page_number": 1,
    })
    assert r.status_code == 404


# ── Update Highlight ──


@pytest.mark.asyncio
async def test_update_highlight(client, seed_highlight):
    """Update a highlight's note and color."""
    headers, _, h, _ = seed_highlight
    r = await client.put(f"/api/v1/highlights/{h.id}", json={
        "note": "Updated note", "color": "#0000ff",
    }, headers=headers)
    assert r.status_code == 200
    assert r.json()["status"] == "updated"


@pytest.mark.asyncio
async def test_update_highlight_not_found(client, auth_ctx):
    """Update non-existent highlight returns 404."""
    headers, _ = auth_ctx
    r = await client.put(f"/api/v1/highlights/{uuid.uuid4()}", json={
        "note": "test",
    }, headers=headers)
    assert r.status_code == 404


# ── Delete Highlight ──


@pytest.mark.asyncio
async def test_delete_highlight(client, seed_highlight):
    """Delete a highlight."""
    headers, _, h, _ = seed_highlight
    r = await client.delete(f"/api/v1/highlights/{h.id}", headers=headers)
    assert r.status_code == 200
    assert r.json()["status"] == "deleted"


@pytest.mark.asyncio
async def test_delete_highlight_not_found(client, auth_ctx):
    """Delete non-existent highlight returns 404."""
    headers, _ = auth_ctx
    r = await client.delete(f"/api/v1/highlights/{uuid.uuid4()}", headers=headers)
    assert r.status_code == 404
