import { createReactiveState } from '@star-kitten/util/reactive-state.js';
import type { PartialContext } from './command-context.type';
import { isApplicationCommand, isAutocomplete } from './command-helpers';
import type { ExecutableInteraction } from './command-handler';

export interface CommandState<T = any> {
  id: string; // unique id for this command instance
  name: string; // command name
  data: T; // internal data storage
}

export async function getCommandState<T>(interaction: ExecutableInteraction, ctx: PartialContext): Promise<CommandState<T>> {
  const id = instanceIdFromInteraction(interaction);

  let state: CommandState<T>;

  // get state from kv store if possible
  if (ctx.kv.has(`command-state:${id}`)) {
    state = await ctx.kv.get<CommandState<T>>(`command-state:${id}`);
  }
  if (!state) {
    state = { id: id, name: '', data: {} as T };
  }
  const [reactiveState, subscribe] = createReactiveState(state);
  subscribe(async (newState) => {
    if (ctx.kv) {
      await ctx.kv.set(`command-state:${id}`, newState);
    }
  });
  ctx.state = reactiveState;
  return reactiveState;
}

function instanceIdFromInteraction(interaction: ExecutableInteraction) {
  if (isAutocomplete(interaction)) {
    // autocomplete should not be stateful, they get no id
    return '';
  }

  if (isApplicationCommand(interaction)) {
    // for application commands, we create a new instance id
    const instance_id = crypto.randomUUID();
    return instance_id;
  }

  const interact = interaction;
  const customId: string = interact.data.custom_id;
  const commandId = customId.split('_').pop();
  interaction;
  // command id should be a uuid
  if (commandId && /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(commandId)) {
    return commandId;
  }
  console.error(`Invalid command id extracted from interaction: ${customId}`);
  return '';
}
