import { type ApplicationCommandStructure } from '@projectdysnomia/dysnomia';
import { getCommandName, isApplicationCommand, isAutocomplete, isMessageComponent, isModalSubmit } from './command-helpers';
import type { PartialContext } from './command-context.type';
import type { CommandHandler, ExecutableInteraction } from './command-handler';
import { injectInteraction } from './command-injection';
import { getCommandState } from './command-state';

export async function handleCommands(
  interaction: ExecutableInteraction,
  commands: Record<string, CommandHandler<ApplicationCommandStructure>>,
  ctx: PartialContext,
) {
  ctx.state = await getCommandState(interaction, ctx);
  if (!ctx.state.name) {
    ctx.state.name = getCommandName(interaction);
  }

  if (isAutocomplete(interaction) && ctx.state.name) {
    const acCommand = commands[ctx.state.name];
    return acCommand.execute(interaction, ctx as any);
  }

  if (!ctx.state.id) {
    console.error(`No command ID found for interaction ${interaction.id}`);
    return;
  }

  const command = commands[ctx.state.name || ''];
  if (!command) {
    console.warn(`No command found for interaction: ${JSON.stringify(interaction, undefined, 2)}`);
    return;
  }
  cleanInteractionCustomIds(interaction, ctx.state.id);
  const [injectedInteraction, fullContext] = await injectInteraction(interaction, ctx);
  return command.execute(injectedInteraction, fullContext);
}

export function initializeCommandHandling(commands: Record<string, CommandHandler<ApplicationCommandStructure>>, ctx: PartialContext) {
  ctx.client.on('interactionCreate', async (interaction) => {
    if (isApplicationCommand(interaction) || isModalSubmit(interaction) || isMessageComponent(interaction) || isAutocomplete(interaction)) {
      handleCommands(interaction, commands, ctx);
    }
  });
}

function cleanInteractionCustomIds(interaction: ExecutableInteraction, id: string) {
  if ('components' in interaction && Array.isArray(interaction.components) && id) {
    removeCommandIdFromComponentCustomIds(interaction.components, id);
  }
  if ('data' in interaction && id) {
    if ('custom_id' in interaction.data && typeof interaction.data.custom_id === 'string') {
      interaction.data.custom_id = interaction.data.custom_id.replace(`_${id}`, '');
    }
    if ('components' in interaction.data && Array.isArray(interaction.data.components)) {
      removeCommandIdFromComponentCustomIds(interaction.data.components as any, id);
    }
  }
}

function removeCommandIdFromComponentCustomIds(components: { custom_id?: string; components?: any[] }[], commandId: string) {
  components.forEach((component) => {
    if ('custom_id' in component) {
      component.custom_id = component.custom_id.replace(`_${commandId}`, '');
    }
    if ('components' in component && Array.isArray(component.components)) {
      removeCommandIdFromComponentCustomIds(component.components, commandId);
    }

    if ('component' in component && 'custom_id' in (component as any).component && Array.isArray(component.components)) {
      (component.component as any).custom_id = (component.component as any).custom_id.replace(`_${commandId}`, '');
    }
  });
}
