import inspect
import json
from pathlib import Path

import pytest

from recoil.execution.execution_store import ExecutionStore
from recoil.execution.pass_store import PassStore
from recoil.pipeline.core.persistence import save_scene
from recoil.pipeline.core.take import Beat, Scene
from recoil.workspace import board
from recoil.workspace import helpers as workspace_helpers
from recoil.workspace import mcp_server


@pytest.fixture
def mcp_board_project(tmp_path, monkeypatch):
    projects_root = tmp_path / "projects"
    projects_root.mkdir()
    (projects_root / ".recoil-data-root").write_text("recoil-data-root\n")
    project = "fixture"
    project_root = projects_root / project
    project_root.mkdir()
    (project_root / "project_config.json").write_text("{}")
    monkeypatch.setenv("RECOIL_PROJECTS_ROOT", str(projects_root))
    workspace_helpers._stores.clear()

    scenes_dir = project_root / "_pipeline" / "state" / "orchestration" / "scenes"
    storyboards_dir = project_root / "prep" / "ep_001" / "storyboards"
    scenes_dir.mkdir(parents=True)
    storyboards_dir.mkdir(parents=True)

    _write_scene(
        scenes_dir / "ep_001_BATCH_001.json",
        "BATCH_001",
        [
            {"segment_id": "EP001_SH01", "setting": "kitchen", "duration_s": 1.5},
            {"segment_id": "EP001_SH02", "setting": "kitchen", "duration_s": 2.0},
        ],
        board_artifact="prep/ep_001/storyboards/BATCH_001_v06.png",
        board_status="proposed",
    )
    _write_sidecar(storyboards_dir / "BATCH_001_v06.png.json", {"status": "proposed"})
    (storyboards_dir / "BATCH_001_v06.png").write_bytes(b"png")

    store = ExecutionStore(project)
    for shot_id in ("EP001_SH01", "EP001_SH02"):
        store.update_shot(shot_id, episode_id="EP001", status="previs_pending")
    store.close()

    passes = PassStore(project)
    passes.create_pass("EP001_PASS_001_SH01_02_TEST", ["EP001_SH01", "EP001_SH02"])
    passes.close()

    yield project

    workspace_helpers._stores.clear()


def test_get_episode_board_matches_board_helper(mcp_board_project):
    project = mcp_board_project

    assert mcp_server.get_episode_board(project, "EP001") == board.build_episode_board(
        project, "EP001"
    )


def test_get_episode_board_tool_registered(mcp_board_project):
    project = mcp_board_project
    tool = mcp_server._TOOLS["get_episode_board"]

    result = tool["handler"]({"project": project, "episode_id": "1"})

    assert tool["name"] == "get_episode_board"
    assert tool["inputSchema"]["required"] == ["project", "episode_id"]
    assert result["episode_id"] == "EP001"
    assert result["batches"][0]["board_artifact"] == (
        "prep/ep_001/storyboards/BATCH_001_v06.png"
    )
    assert result["summary"] == {
        "covered": 2,
        "total": 2,
        "awaiting": 0,
        "review_count": 1,
    }


def test_mcp_board_tool_imports_board_not_server():
    source = inspect.getsource(mcp_server)

    assert mcp_server.board is board
    assert "from recoil.workspace import board" in source
    assert "from recoil.workspace import server" not in source
    assert "from workspace import server" not in source


def _write_scene(
    path: Path,
    batch_id: str,
    batch_shots: list[dict],
    board_artifact: str | None = None,
    board_status: str | None = None,
) -> None:
    beat = Beat(
        beat_id=batch_id,
        beat_metadata={
            "batch_shots": batch_shots,
            "shared_location_id": f"loc_{batch_id.lower()}",
            "shared_characters": ["ada", "ben"],
            "total_duration_s": sum(shot["duration_s"] for shot in batch_shots),
        },
    )
    if board_artifact is not None:
        # REC-231 Phase 4: the wall dereferences the active body's pointed board
        # (beat.board.artifact), not the newest sidecar on disk.
        beat.set_board_proposed(
            artifact=board_artifact, source_sha256="0" * 64, fingerprint_version=1
        )
        if board_status == "approved":
            beat.approve_board("JT")
    save_scene(Scene(scene_id=batch_id, beats=[beat]), path)


def _write_sidecar(path: Path, data: dict) -> None:
    path.write_text(json.dumps(data), encoding="utf-8")
