"""Command/result protocol for ReaScript two-way JSON communication."""

from __future__ import annotations

import json
from dataclasses import dataclass, field
from pathlib import Path


class ProtocolVersionError(Exception):
    """Raised when command/result version doesn't match expected."""

    pass


@dataclass
class ReaScriptCommand:
    version: int = 1
    action: str | list[str] = "calibrate"  # "calibrate" | "verify_fx" | "render" — or list for pipeline
    rpp_path: str = ""
    render_path: str = ""
    timeout: int = 120
    track_calibration: list[dict] = field(default_factory=list)
    plugins_to_add: list[dict] = field(default_factory=list)
    # Each dict: {"track_name": str, "fx_name": str, "params": {"0": float, ...}}


@dataclass
class ReaScriptResult:
    version: int = 1
    status: str = "ok"  # "ok" | "error" | "timeout"
    message: str = ""
    lufs: float | None = None
    integrated_lufs: float | None = None
    short_term_lufs: float | None = None
    fx_errors: list[dict] = field(default_factory=list)
    tracks_verified: int = 0
    added_plugins: list[dict] = field(default_factory=list)
    # Each dict: {"fx_name": str, "instance_id": int, "track_name": str, "status": str}


def write_command(path: Path, cmd: ReaScriptCommand) -> None:
    """Write command JSON file for ReaScript to read."""
    data = {
        "version": cmd.version,
        "action": cmd.action,
        "rpp_path": cmd.rpp_path,
        "render_path": cmd.render_path,
        "timeout": cmd.timeout,
        "track_calibration": cmd.track_calibration,
    }
    if cmd.plugins_to_add:
        data["plugins_to_add"] = cmd.plugins_to_add
    with open(path, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2)


def read_result(path: Path, expected_version: int = 1) -> ReaScriptResult:
    """Read result JSON file written by ReaScript. Raises ProtocolVersionError on mismatch."""
    with open(path, "r", encoding="utf-8") as f:
        data = json.load(f)

    version = data.get("version")
    if version != expected_version:
        raise ProtocolVersionError(
            f"Result version mismatch: expected {expected_version}, got {version}"
        )

    return ReaScriptResult(
        version=data.get("version", 1),
        status=data.get("status", "ok"),
        message=data.get("message", ""),
        lufs=data.get("lufs"),
        integrated_lufs=data.get("integrated_lufs"),
        short_term_lufs=data.get("short_term_lufs"),
        fx_errors=data.get("fx_errors", []),
        tracks_verified=data.get("tracks_verified", 0),
        added_plugins=data.get("added_plugins", []),
    )
