"""Executor for MultiBeatDirectiveProposal.

Appends a directive note to each affected beat's shot JSON.
"""
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/multi_beat_directive"


def execute(
    beat_ids: list[str],
    note: str,
    project_id: Optional[str] = None,
) -> dict:
    """Append note to shot["directives"] for every beat in beat_ids.

    Args:
        beat_ids: List of beat identifiers to apply the directive to.
        note: The directive text.
        project_id: Optional project slug.

    Returns:
        {"beat_ids_updated": list[str], "directive_applied": True}

    Raises:
        HTTPException(404): If any beat_id not found on disk.
    """
    try:
        result = beats_adapter.add_directive_to_beats(
            beat_ids=beat_ids, note=note, project_id=project_id
        )
    except KeyError as exc:
        BUS.emit_sync(
            severity="failure",
            scope=_SCOPE,
            summary="multi_beat_directive_target_not_found",
            payload={"beat_ids": beat_ids, "error": str(exc)},
        )
        raise HTTPException(
            status_code=404,
            detail={
                "error": "beat_not_found",
                "beat_ids": beat_ids,
                "message": str(exc),
            },
        )
    BUS.emit_sync(
        severity="success",
        scope=_SCOPE,
        summary=f"multi_beat_directive_applied: {len(beat_ids)} beats",
        payload={**result, "note_length": len(note)},
    )
    return result
