"""Task A6 — 통합(E2E 단위) + 중복 0 회귀.

generation_context scope 안에서 capture → 블록 종료 finally flush → DB intermediate
1행(input_image_ids 보존, 파일 실재). scope 미사용(최종물 경로 시뮬)은 0행(중복 0).
"""

import json
import uuid
from datetime import datetime, timezone
from pathlib import Path

from app.core.database import SessionLocal
from app.models.catalog import ProjectRegistry, UserAccount
from app.models.project import Episode, ImageAsset
from app.services.image_capture.context import generation_context
from app.services.image_capture.queue import CAPTURE_DIAG
from app.services.image_capture.sink import capture_generated_image


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _seed_base(db) -> tuple[str, str]:
    uid = str(uuid.uuid4())
    db.add(UserAccount(
        id=uid, username=f"u_{uid[:8]}", display_name="t", password_hash="x",
        role="admin", created_at=_now(), updated_at=_now(),
    ))
    db.commit()
    pid = str(uuid.uuid4())
    db.add(ProjectRegistry(
        id=pid, name="Integration Test", created_by=uid, created_at=_now(), updated_at=_now(),
    ))
    eid = str(uuid.uuid4())
    db.add(Episode(
        id=eid, project_id=pid, episode_number=1, title="Pilot",
        source_filename="p.pdf", source_path="p.pdf", created_at=_now(), updated_at=_now(),
    ))
    db.commit()
    return pid, eid


def test_scope_capture_persists_intermediate_with_lineage():
    db = SessionLocal()
    try:
        pid, eid = _seed_base(db)
    finally:
        db.close()

    bg, base = str(uuid.uuid4()), str(uuid.uuid4())
    with generation_context(pid, eid, "pose_guide") as _q:
        capture_generated_image(
            b"GUIDEPNG", role="pose_guide", input_image_ids=[bg, base]
        )
    # 블록 종료 finally 에서 flush 발생 — 별도 세션 조회

    db = SessionLocal()
    try:
        rows = (
            db.query(ImageAsset)
            .filter(ImageAsset.project_id == pid, ImageAsset.is_intermediate == True)  # noqa: E712
            .all()
        )
        assert len(rows) == 1
        row = rows[0]
        assert row.pipeline_role == "pose_guide"
        assert row.stage == "pose_guide"
        assert json.loads(row.input_image_ids) == [bg, base]
        assert Path(row.file_path).exists()
        assert Path(row.file_path).read_bytes() == b"GUIDEPNG"
    finally:
        db.close()


def test_no_scope_capture_creates_zero_rows():
    """최종물 경로(scope 미사용) 시뮬 — image_asset 중복 0."""
    db = SessionLocal()
    try:
        pid, eid = _seed_base(db)
    finally:
        db.close()

    before = CAPTURE_DIAG["skipped_no_context"]
    # scope 안 염 — 최종물처럼 직접 호출
    capture_generated_image(b"FINALPNG", role="final_scene")
    assert CAPTURE_DIAG["skipped_no_context"] == before + 1

    db = SessionLocal()
    try:
        n = (
            db.query(ImageAsset)
            .filter(ImageAsset.project_id == pid)
            .count()
        )
        assert n == 0  # 중복 0 — sink 가 최종물 경로를 만들지 않음
    finally:
        db.close()
