"""Executor for BeatInsertionProposal.

Creates a new shot JSON file with prompt_override set to the proposal text.
"""
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/beat_insertion"


def execute(
    episode_id: str,
    text: str,
    project_id: Optional[str] = None,
    after_beat_id: Optional[str] = None,
) -> dict:
    """Create a new beat (shot JSON file) in the given episode.

    Args:
        episode_id: Episode identifier (e.g. "EP001").
        text: Visual description for the new beat (becomes prompt_override).
        project_id: Required project slug.
        after_beat_id: Optional beat to insert after (stored as metadata).

    Returns:
        {"shot_id": str, "episode_id": str, "beat_insertion_applied": True}

    Raises:
        HTTPException(422): If project_id is absent or empty.
        HTTPException(404): If the project's shots directory does not exist.
    """
    if not project_id:
        raise HTTPException(
            status_code=422,
            detail={
                "error": "project_id_required",
                "message": "BeatInsertionProposal requires project_id",
            },
        )
    try:
        result = beats_adapter.insert_beat(
            episode_id=episode_id,
            text=text,
            project_id=project_id,
            after_beat_id=after_beat_id,
        )
    except KeyError as exc:
        BUS.emit_sync(
            severity="failure",
            scope=_SCOPE,
            summary=f"beat_insertion_target_not_found: {episode_id}",
            payload={
                "episode_id": episode_id,
                "project_id": project_id,
                "error": str(exc),
            },
        )
        raise HTTPException(
            status_code=404,
            detail={
                "error": "shots_dir_not_found",
                "episode_id": episode_id,
                "project_id": project_id,
                "message": str(exc),
            },
        )
    BUS.emit_sync(
        severity="success",
        scope=_SCOPE,
        summary=f"beat_insertion_applied: {result['shot_id']}",
        payload={
            **result,
            "episode_id": episode_id,
            "after_beat_id": after_beat_id,
            "text_length": len(text),
        },
    )
    return result
