"""Agent-friendly tag analysis endpoints (#1136): /api/tags/top + /tags/<id>/stats."""
import pytest

from backend.app.models import ImageRecord, TagHead, TagKind
from backend.app.models.tag import image_tag
from backend.app.models.tag_suggestion_rejection import TagSuggestionRejection
from backend.app.services.tag_service import TagService

pytestmark = pytest.mark.integration


async def _img(db, sha) -> ImageRecord:
    img = ImageRecord(
        path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
        width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
    )
    db.add(img)
    await db.flush()
    return img


async def _apply(db, image_id, tag_id, source):
    await db.execute(image_tag.insert().values(
        image_record_id=image_id, tag_id=tag_id, source=source,
    ))


@pytest.mark.asyncio
async def test_tags_top_ranks_by_count_and_filters(client, db):
    svc = TagService(db)
    common = await svc.find_or_create("Common", TagKind.general)
    rare = await svc.find_or_create("Rare", TagKind.general)
    imgs = [await _img(db, f"{i:064d}") for i in range(3)]
    await _apply(db, imgs[0].id, common.id, "manual")
    await _apply(db, imgs[1].id, common.id, "manual")
    await _apply(db, imgs[2].id, common.id, "head_auto")   # 3 total, 2 human
    await _apply(db, imgs[0].id, rare.id, "manual")         # 1
    await db.commit()

    top = await (await client.get("/api/tags/top?kind=general&limit=10")).get_json()
    counts = {t["name"]: t["count"] for t in top["tags"]}
    assert counts["Common"] == 3 and counts["Rare"] == 1
    assert [t["name"] for t in top["tags"]][0] == "Common"   # count desc

    # source=human drops the head_auto application
    human = await (await client.get("/api/tags/top?source=human&kind=general")).get_json()
    assert {t["name"]: t["count"] for t in human["tags"]}["Common"] == 2

    # min_count filters out the rare tag
    mc = await (await client.get("/api/tags/top?min_count=2&kind=general")).get_json()
    assert "Rare" not in [t["name"] for t in mc["tags"]]


@pytest.mark.asyncio
async def test_tag_stats_source_breakdown(client, db):
    svc = TagService(db)
    tag = await svc.find_or_create("Hero", TagKind.character)
    i1, i2, i3, i4 = [await _img(db, c * 64) for c in "abcd"]
    await _apply(db, i1.id, tag.id, "manual")
    await _apply(db, i2.id, tag.id, "ml_accepted")
    await _apply(db, i3.id, tag.id, "ccip_auto")
    db.add(TagSuggestionRejection(image_record_id=i4.id, tag_id=tag.id))
    db.add(TagHead(
        tag_id=tag.id, embedding_version="v", weights=[0.0] * 1152, bias=0.0,
        suggest_threshold=0.5, auto_apply_threshold=None, n_pos=10, n_neg=30,
        ap=0.8, precision_cv=0.9, recall=0.6,
    ))
    await db.commit()

    body = await (await client.get(f"/api/tags/{tag.id}/stats")).get_json()
    assert body["count_total"] == 3
    assert body["count_human"] == 2          # manual + ml_accepted
    assert body["count_manual"] == 1
    assert body["count_accepted"] == 1
    assert body["count_ccip_auto"] == 1
    assert body["count_auto"] == 1
    assert body["count_rejected"] == 1
    assert body["has_head"] is True


@pytest.mark.asyncio
async def test_tag_stats_404(client):
    resp = await client.get("/api/tags/99999/stats")
    assert resp.status_code == 404
