import type { ExtensionDefinition } from "../types";

type PollState = {
    pollId: string | null;
    isOpen: boolean;
    question: string;
    votes: {
        yes: number;
        no: number;
    };
};

const EMPTY_POLL: PollState = {
    pollId: null,
    isOpen: false,
    question: "",
    votes: {
        yes: 0,
        no: 0
    }
};

function normalizeVote(input: string | undefined): "yes" | "no" | null {
    if (!input) {
        return null;
    }
    const value = input.trim().toLowerCase();
    if (value === "yes" || value === "y" || value === "1") {
        return "yes";
    }
    if (value === "no" || value === "n" || value === "0") {
        return "no";
    }
    return null;
}

export const pollsExtension: ExtensionDefinition = {
    id: "polls",
    init(api) {
        api.registerQuickAction({
            id: "polls.status",
            label: "Poll Status",
            description: "Broadcast current poll state to admin/overlay",
            run: async ({ streamId, tokenId, sessionId }) => {
                await api.emit("chat_command", {
                    streamId,
                    command: "poll",
                    args: ["status"],
                    source: "chat",
                    origin: "admin",
                    actor: {
                        role: "admin",
                        platform: "local",
                        userId: tokenId,
                        username: sessionId ?? undefined
                    }
                });
            }
        });

        api.registerQuickAction({
            id: "polls.end",
            label: "Poll End",
            description: "End currently active poll",
            run: async ({ streamId, tokenId, sessionId }) => {
                await api.emit("chat_command", {
                    streamId,
                    command: "poll",
                    args: ["end"],
                    source: "chat",
                    origin: "admin",
                    actor: {
                        role: "admin",
                        platform: "local",
                        userId: tokenId,
                        username: sessionId ?? undefined
                    }
                });
            }
        });

        api.on("chat_command", async (event) => {
            if (event.payload.command !== "poll") {
                return;
            }

            const action = event.payload.args[0]?.toLowerCase() ?? "";
            const state = api.getState<PollState>(event.payload.streamId, "active", EMPTY_POLL);
            const isAdminActor = event.payload.actor.role === "admin";

            if (action === "start") {
                if (!isAdminActor) {
                    return;
                }
                const question = event.payload.args.slice(1).join(" ").trim() || "Do you agree?";
                const nextState: PollState = {
                    pollId: null,
                    isOpen: true,
                    question,
                    votes: { yes: 0, no: 0 }
                };
                const pollRecord = await api.db.createPoll({
                    streamId: event.payload.streamId,
                    question,
                    isOpen: true,
                    votesYes: 0,
                    votesNo: 0
                });
                nextState.pollId = pollRecord.id;
                api.setState(event.payload.streamId, "active", nextState);

                await api.emit("ws_out", {
                    streamId: event.payload.streamId,
                    target: "all",
                    event: "poll_update",
                    data: nextState
                });
                return;
            }

            if (action === "vote") {
                if (!state.isOpen) {
                    return;
                }

                const vote = normalizeVote(event.payload.args[1]);
                if (!vote) {
                    return;
                }

                const nextState: PollState = {
                    ...state,
                    votes: {
                        ...state.votes,
                        [vote]: state.votes[vote] + 1
                    }
                };
                if (state.pollId) {
                    await api.db.updatePoll(state.pollId, {
                        votesYes: nextState.votes.yes,
                        votesNo: nextState.votes.no
                    });
                }
                api.setState(event.payload.streamId, "active", nextState);

                await api.emit("ws_out", {
                    streamId: event.payload.streamId,
                    target: "all",
                    event: "poll_update",
                    data: nextState
                });
                return;
            }

            if (action === "status") {
                await api.emit("ws_out", {
                    streamId: event.payload.streamId,
                    target: "all",
                    event: "poll_update",
                    data: state
                });
                return;
            }

            if (action === "end") {
                if (!isAdminActor) {
                    return;
                }
                if (!state.isOpen) {
                    return;
                }

                const nextState: PollState = {
                    ...state,
                    isOpen: false
                };
                if (state.pollId) {
                    await api.db.updatePoll(state.pollId, {
                        isOpen: false,
                        votesYes: nextState.votes.yes,
                        votesNo: nextState.votes.no
                    });
                }
                api.setState(event.payload.streamId, "active", nextState);

                await api.emit("ws_out", {
                    streamId: event.payload.streamId,
                    target: "all",
                    event: "poll_update",
                    data: nextState
                });
            }
        });
    }
};
