"""CP-7 Phase 2 — Take / Beat / Scene JSON round-trip tests."""

import sys
import pathlib
import json

sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent.parent.parent))
from recoil.core.paths import ensure_pipeline_importable  # noqa: E402
ensure_pipeline_importable()

import pytest  # noqa: E402

from recoil.pipeline.core.receipts import GenerationReceipt  # noqa: E402
from recoil.pipeline.core.registry import RunResult  # noqa: E402
from recoil.pipeline.core.take import Beat, Scene, Take  # noqa: E402
from recoil.pipeline.core.workflow import Workflow, WorkflowStep  # noqa: E402


def _sample_receipt(modality="image_t2i", shot_id="X", success=True) -> GenerationReceipt:
    rr = RunResult(
        id=f"{shot_id}_{modality}_1700000000",
        modality=modality,
        output_path="/tmp/x.png" if success else None,
        output_url=None,
        metadata={
            "cost_usd": 0.04, "final_state": "keyframe_generated",
            "model": "nbp", "pipeline": "still",
            "gate_verdict": None, "take_index": 0,
        },
        success=success,
        error=None if success else "boom",
    )
    return GenerationReceipt(
        receipt_id=f"rcpt_1_{shot_id}_{modality}",
        modality=modality,
        caller_id="test",
        project="tartarus",
        episode=1,
        shot_id=shot_id,
        timestamp_utc="2026-04-27T03:14:15Z",
        run_result=rr,
        provenance={"dispatch_path": "test", "model": "nbp"},
        eval_scores={},
    )


def _wf(workflow_id="wf1", with_receipt=False) -> Workflow:
    step = WorkflowStep(
        step_id="kf", modality="image_t2i",
        payload={"shot_id": "X", "prompt": "p", "model": "nbp"},
    )
    if with_receipt:
        step.status = "succeeded"
        step.receipt = _sample_receipt()
        step.started_us = 1700000000_000_000
        step.finished_us = 1700000000_500_000
    return Workflow(workflow_id=workflow_id, steps=[step])


def test_take_round_trip_pending():
    t = Take(take_id="t0", take_index=0, workflow=_wf(),
             take_metadata={"model": "nbp"})
    t2 = Take.from_dict(t.to_dict())
    assert t2.take_id == t.take_id and t2.take_index == 0 and t2.status == "pending"
    assert t2.take_metadata == {"model": "nbp"} and t2.workflow.workflow_id == "wf1"


def test_take_round_trip_with_executed_workflow():
    t = Take(take_id="t0", take_index=0, workflow=_wf(with_receipt=True),
             status="succeeded")
    t2 = Take.from_dict(t.to_dict())
    assert t2.status == "succeeded"
    assert t2.workflow.steps[0].status == "succeeded"
    assert t2.workflow.steps[0].receipt is not None
    assert t2.workflow.steps[0].receipt.run_result.success is True


def test_take_to_dict_is_json_serializable():
    t = Take(take_id="t0", take_index=0, workflow=_wf(with_receipt=True),
             status="succeeded", take_metadata={"model": "nbp"})
    s = json.dumps(t.to_dict())
    assert "wf1" in s and "succeeded" in s and "nbp" in s


def test_beat_round_trip_empty():
    b2 = Beat.from_dict(Beat(beat_id="EP001_SH02").to_dict())
    assert b2.beat_id == "EP001_SH02" and b2.takes == [] and b2.primary_take_id is None


def test_beat_round_trip_with_takes():
    b = Beat(beat_id="EP001_SH02",
             beat_metadata={"scene_id": "scene_3"})
    b.new_take(workflow=_wf("wf1"))
    b.new_take(workflow=_wf("wf2"))
    b.primary_take_id = "EP001_SH02_take_0"
    b2 = Beat.from_dict(b.to_dict())
    assert len(b2.takes) == 2
    assert [t.take_id for t in b2.takes] == ["EP001_SH02_take_0", "EP001_SH02_take_1"]
    assert b2.primary_take_id == "EP001_SH02_take_0"
    assert b2.primary_take.take_id == "EP001_SH02_take_0"
    assert b2.beat_metadata == {"scene_id": "scene_3"}


def test_scene_round_trip_with_beats():
    b1 = Beat(beat_id="EP001_SH02")
    b1.new_take(workflow=_wf("wf1"))
    b2 = Beat(beat_id="EP001_SH03")
    b2.new_take(workflow=_wf("wf2"))
    s = Scene(scene_id="ep001_sc02", beats=[b1, b2],
              scene_metadata={"location": "hallway"})
    s2 = Scene.from_dict(s.to_dict())
    assert s2.scene_id == "ep001_sc02"
    assert [b.beat_id for b in s2.beats] == ["EP001_SH02", "EP001_SH03"]
    assert s2.scene_metadata == {"location": "hallway"}
    assert s2.beats[0].takes[0].take_id == "EP001_SH02_take_0"
    # JSON serializable
    assert json.dumps(s.to_dict())


def test_scene_round_trip_empty():
    s2 = Scene.from_dict(Scene(scene_id="s1").to_dict())
    assert s2.scene_id == "s1" and s2.beats == []


def test_take_round_trip_preserves_nested_metadata():
    t = Take(take_id="t0", take_index=0, workflow=_wf(),
             take_metadata={"a": 1, "b": "two", "c": [1, 2, 3], "d": {"e": "f"}})
    t2 = Take.from_dict(t.to_dict())
    assert t2.take_metadata == t.take_metadata
