"""Executor for PromptRewriteProposal.

Writes shot["prompt_override"] = new_text to the shot JSON via the
beats adapter and emits a BUS event.

Scope boundary: prompt_override is read by recoil/core/prompt_compiler.py
(keyframe path only). recoil/pipeline/_lib/prompt_engine.py (video/multi-modal)
does not read it — video-side override wiring is a separate follow-on.
"""
from __future__ import annotations

import logging
from typing import Optional

from fastapi import HTTPException

from recoil.api.adapters import beats as beats_adapter
from recoil.api.eventbus import BUS

logger = logging.getLogger(__name__)

_SCOPE = "api/executors/prompt_rewrite"


def execute(beat_id: str, new_text: str, project_id: Optional[str] = None) -> dict:
    """Write new_text to shot["prompt_override"] on disk.

    Args:
        beat_id: Shot file stem (e.g. "EP001_SH02"). Must match a .json
                 file in projects/{project}/state/visual/shots/.
        new_text: The full replacement prompt text.
        project_id: Optional project slug. If None, all projects are scanned.

    Returns:
        {"shot_id": str, "prompt_override_set": True}

    Raises:
        HTTPException(404): If beat_id resolves to no shot file on disk.
    """
    try:
        result = beats_adapter.set_prompt_override(beat_id, new_text, project_id)
    except KeyError:
        BUS.emit_sync(
            severity="failure",
            scope=_SCOPE,
            summary=f"prompt_rewrite_target_not_found: {beat_id}",
            payload={
                "beat_id": beat_id,
                "note": "beat_id not found in any project shots directory",
            },
        )
        raise HTTPException(
            status_code=404,
            detail={
                "error": "beat_not_found",
                "beat_id": beat_id,
                "message": (
                    f"Cannot rewrite prompt: beat {beat_id!r} does not exist on disk. "
                    "Check that the project is loaded and the beat ID is correct."
                ),
            },
        )
    BUS.emit_sync(
        severity="success",
        scope=_SCOPE,
        summary=f"prompt_rewrite_applied: {beat_id}",
        payload={
            **result,
            "beat_id": beat_id,
            "new_text_length": len(new_text),
        },
    )
    return result
