"""Task B4 — fal apply_fal_angle capture 계측 테스트.

result_url 다운로드 bytes(data = dl.read())가 실제 output → capture_generated_image.
resize 된 input bytes 는 output 이 아니므로 capture 대상 아님. default-off.
"""

import json
from unittest.mock import MagicMock

from app.services.image_capture.context import generation_context
from app.services.image_capture.queue import CAPTURE_DIAG

_FAL_PAYLOAD = b"FALRESULTPNG" * 8


class _JsonResp:
    def __enter__(self):
        return self

    def __exit__(self, *a):
        return False

    def read(self):
        return json.dumps({"images": [{"url": "https://fal.result/img.png"}]}).encode()


class _BytesResp:
    def __enter__(self):
        return self

    def __exit__(self, *a):
        return False

    def read(self):
        return _FAL_PAYLOAD


def _fake_urlopen(arg, timeout=None):
    # 첫 호출=fal.run Request(객체) → JSON, 둘째=result_url(str) → bytes.
    if isinstance(arg, str):
        return _BytesResp()
    return _JsonResp()


def _setup(monkeypatch):
    import app.services.fal_angle_helpers as fa

    monkeypatch.setattr(fa.urllib.request, "urlopen", _fake_urlopen)
    fake_tracer = MagicMock()
    fake_tracer.log = MagicMock()
    monkeypatch.setattr(
        "app.modules.llm.image_tracer.get_image_tracer", lambda: fake_tracer
    )
    return fa


def test_fal_captures_result_inside_scope(monkeypatch):
    fa = _setup(monkeypatch)
    with generation_context("p-fal", "e-fal", "fal_angle") as q:
        data, _ms = fa.apply_fal_angle(b"input-bytes", 90.0, 0.0, 1.0)
        assert data == _FAL_PAYLOAD
        assert len(q._items) == 1
        _spool, meta = q._items[0]
        assert meta["pipeline_role"] == "fal_angle"
        assert meta["pipeline_metadata"]["horizontal"] == 90.0


def test_fal_no_capture_outside_scope(monkeypatch):
    fa = _setup(monkeypatch)
    before = CAPTURE_DIAG["skipped_no_context"]
    data, _ms = fa.apply_fal_angle(b"input-bytes", 0.0, 0.0, 1.0)
    assert data == _FAL_PAYLOAD
    assert CAPTURE_DIAG["skipped_no_context"] >= before + 1
