import type { InMemoryEventBus } from "./eventBus";
import { createEvent } from "./events";
import { LIMITS } from "./limits";

type ParserLog = (message: string, fields?: Record<string, unknown>) => void;

function parseCommand(rawMessage: string): { command: string; args: string[] } | null {
    const message = rawMessage.trimStart();
    if (!message.startsWith("!")) {
        return null;
    }

    const commandLine = message.slice(1).trim();
    if (!commandLine) {
        return null;
    }
    if (commandLine.length > LIMITS.MAX_COMMAND_LINE_LENGTH) {
        return null;
    }

    const parts = commandLine.split(/\s+/);
    const command = parts[0]?.trim().toLowerCase() ?? "";
    const args = parts.slice(1);

    if (!command) {
        return null;
    }
    if (command.length > LIMITS.MAX_COMMAND_LENGTH) {
        return null;
    }
    if (args.length > LIMITS.MAX_ARGS_COUNT) {
        return null;
    }
    if (args.some((arg) => arg.length > LIMITS.MAX_ARG_LENGTH)) {
        return null;
    }

    return { command, args };
}

export function attachChatCommandParser(
    eventBus: InMemoryEventBus,
    log: ParserLog
): () => void {
    return eventBus.on(
        "chat_message",
        async (event) => {
            const parsed = parseCommand(event.payload.message);
            if (!parsed) {
                return;
            }

            await eventBus.emit(
                createEvent("chat_command", {
                    streamId: event.payload.streamId,
                    command: parsed.command,
                    args: parsed.args,
                    source: "chat",
                    origin: "chat",
                    actor: {
                        role: "unknown",
                        platform:
                            event.payload.platform === "youtube" || event.payload.platform === "twitch"
                                ? event.payload.platform
                                : undefined,
                        username: event.payload.author
                    }
                })
            );

            log("chat_command_parsed", {
                streamId: event.payload.streamId,
                command: parsed.command,
                argsCount: parsed.args.length
            });
        },
        {
            componentId: "chat-command-parser",
            componentKind: "core"
        }
    );
}
