from dataclasses import dataclass
from typing import Dict, Optional

from ...channels.plugins.message_actions import dispatch_channel_message_action
from ...channels.plugins.types import ChannelActionContext, ChannelMessageActionName
from ...channels.registry import normalize_channel_id
from ...config import DemoConfig


@dataclass
class RunMessageActionParams:
    cfg: DemoConfig
    action: ChannelMessageActionName
    params: Dict[str, object]
    default_account_id: Optional[str] = None
    dry_run: bool = False


def _resolve_channel(cfg: DemoConfig, params: Dict[str, object]) -> str:
    raw = params.get("channel")
    channel = normalize_channel_id(str(raw)) if raw is not None else None
    if channel is None:
        channel = normalize_channel_id(cfg.default_channel)
    if channel is None:
        raise ValueError("No valid channel resolved.")
    if channel not in cfg.enabled_channels:
        raise ValueError(f"Channel {channel} is not enabled.")
    return channel


def _normalize_target(params: Dict[str, object]) -> None:
    target = str(params.get("target", "")).strip()
    to = str(params.get("to", "")).strip()
    if target and not to:
        params["to"] = target
    if not str(params.get("to", "")).strip():
        raise ValueError("Action requires a target. Pass --to or --target.")


def run_message_action(input_data: RunMessageActionParams) -> dict:
    args = dict(input_data.params)
    channel = _resolve_channel(input_data.cfg, args)

    if input_data.action in ("send", "poll", "react", "delete"):
        _normalize_target(args)

    if input_data.action == "broadcast":
        raw_targets = args.get("targets", [])
        if not isinstance(raw_targets, list) or not raw_targets:
            raise ValueError("Broadcast requires non-empty --targets.")
        if input_data.dry_run:
            return {"kind": "broadcast", "handled_by": "dry-run", "results": raw_targets}
        return {
            "kind": "broadcast",
            "handled_by": "core",
            "results": [{"channel": channel, "to": target, "ok": True} for target in raw_targets],
        }

    if input_data.dry_run:
        return {
            "kind": "action",
            "channel": channel,
            "action": input_data.action,
            "handled_by": "dry-run",
            "payload": {"ok": True},
        }

    handled = dispatch_channel_message_action(
        ChannelActionContext(
            channel=channel,
            action=input_data.action,
            params=args,
            account_id=input_data.default_account_id,
        )
    )
    if handled is None:
        raise ValueError(f"No plugin registered for channel {channel}")
    return {
        "kind": "action",
        "channel": channel,
        "action": input_data.action,
        "handled_by": "plugin",
        "payload": handled,
    }

