"""FC-6.x Phase 2 — pending staging for add-from-post."""

import pytest
from sqlalchemy import select

from backend.app.models import Artist, ImageRecord, Post, TagKind
from backend.app.models.series_page import SeriesPage
from backend.app.services.series_service import SeriesService
from backend.app.services.tag_service import TagService

pytestmark = pytest.mark.integration

_SEQ = 0


async def _artist(db, name):
    a = Artist(name=name, slug=name.lower().replace(" ", "-"))
    db.add(a)
    await db.flush()
    return a


async def _post(db, artist, title, ext):
    p = Post(artist_id=artist.id, external_post_id=ext, post_title=title)
    db.add(p)
    await db.flush()
    return p


async def _post_images(db, post, artist, n):
    global _SEQ
    ids = []
    for _ in range(n):
        _SEQ += 1
        rec = ImageRecord(
            path=f"/tmp/fc_pend_{_SEQ}.png", sha256=f"{_SEQ:064d}",
            size_bytes=1, mime="image/png", origin="downloaded",
            primary_post_id=post.id, artist_id=artist.id,
        )
        db.add(rec)
        await db.flush()
        ids.append(rec.id)
    return ids


async def _placed_order(db, sid):
    rows = (
        await db.execute(
            select(SeriesPage.image_id)
            .where(
                SeriesPage.series_tag_id == sid,
                SeriesPage.status == "placed",
            )
            .order_by(SeriesPage.page_number)
        )
    ).scalars().all()
    return list(rows)


async def _setup(db, name, seed_n=2):
    svc = SeriesService(db)
    artist = await _artist(db, name + " Artist")
    sid = (await TagService(db).find_or_create(name, TagKind.series)).id
    seed = []
    if seed_n:
        seed_post = await _post(db, artist, name + " seed", name + "-s")
        seed = await _post_images(db, seed_post, artist, seed_n)
        await svc.add_images(sid, seed)
    return svc, artist, sid, seed


@pytest.mark.asyncio
async def test_place_pending_appends_and_flips_status(db):
    svc, artist, sid, seed = await _setup(db, "PA")
    post = await _post(db, artist, "PA pages", "pa-p")
    imgs = await _post_images(db, post, artist, 3)
    await svc.add_post(sid, post.id)

    placed = await svc.place_pending(sid, imgs, start_page=3)
    assert placed == 3
    assert await _placed_order(db, sid) == seed + imgs
    # nothing left pending; the placed pages are numbered 1,2 (seed) + 3,4,5
    data = await svc.list_pages(sid)
    assert data["pending"] == []
    assert [p["page_number"] for p in data["pages"]] == [1, 2, 3, 4, 5]


@pytest.mark.asyncio
async def test_place_pending_numbers_from_start(db):
    svc, artist, sid, seed = await _setup(db, "PB")  # seed numbered 1, 2
    post = await _post(db, artist, "PB pages", "pb-p")
    x, y = await _post_images(db, post, artist, 2)
    await svc.add_post(sid, post.id)

    await svc.place_pending(sid, [x, y], start_page=10)
    data = await svc.list_pages(sid)
    nums = {p["image_id"]: p["page_number"] for p in data["pages"]}
    assert nums[x] == 10
    assert nums[y] == 11
    # order = seed (1, 2) then x (10), y (11)
    assert [p["image_id"] for p in data["pages"]] == seed + [x, y]


@pytest.mark.asyncio
async def test_place_pending_ignores_already_placed(db):
    svc, artist, sid, seed = await _setup(db, "PC", seed_n=1)
    # the seed page is already placed — place_pending is a no-op for it.
    assert await svc.place_pending(sid, [seed[0]]) == 0
    assert await _placed_order(db, sid) == seed


@pytest.mark.asyncio
async def test_remove_drops_a_pending_junk_page(db):
    svc, artist, sid, _ = await _setup(db, "PD", seed_n=0)
    post = await _post(db, artist, "PD pages", "pd-p")
    x, y, z = await _post_images(db, post, artist, 3)
    await svc.add_post(sid, post.id)
    # y is junk (a text-free alt) — drop it before placing.
    await svc.remove_images(sid, [y])
    data = await svc.list_pages(sid)
    assert [pg["image_id"] for pg in data["pending"][0]["pages"]] == [x, z]


@pytest.mark.asyncio
async def test_place_pending_route_requires_ids(client):
    r = await client.post(
        "/api/tags", json={"name": "PReq", "kind": "series"}
    )
    sid = (await r.get_json())["id"]
    resp = await client.post(f"/api/series/{sid}/pending/place", json={})
    assert resp.status_code == 400
