import { type InteractionModalContent, type Component } from '@projectdysnomia/dysnomia';
import type { CommandContext, PartialContext } from './command-context.type';
import { isApplicationCommand, isMessageComponent } from './command-helpers';
import type { ExecutableInteraction } from './command-handler';

export function injectInteraction(interaction: ExecutableInteraction, ctx: PartialContext): [ExecutableInteraction, CommandContext] {
  // Wrap the interaction methods to inject command tracking ids into all custom_ids for modals and components.
  if (ctx.state.name && (isApplicationCommand(interaction) || isMessageComponent(interaction))) {
    const _originalCreateModal = interaction.createModal.bind(interaction);
    interaction.createModal = (content: InteractionModalContent) => {
      validateCustomIdLength(content.custom_id);
      content.custom_id = `${content.custom_id}_${ctx.state.id}`;
      return _originalCreateModal(content);
    };

    const _originalCreateMessage = interaction.createMessage.bind(interaction);
    interaction.createMessage = (content) => {
      if (typeof content === 'string') return _originalCreateMessage(content);
      if (content.components) {
        addCommandIdToComponentCustomIds(content.components, ctx.state.id);
      }
      return _originalCreateMessage(content);
    };

    const _originalEditMessage = interaction.editMessage.bind(interaction);
    interaction.editMessage = (messageID, content) => {
      if (typeof content === 'string') return _originalEditMessage(messageID, content);
      if (content.components) {
        addCommandIdToComponentCustomIds(content.components, ctx.state.id);
      }
      return _originalEditMessage(messageID, content);
    };

    const _originalCreateFollowup = interaction.createFollowup.bind(interaction);
    interaction.createFollowup = (content) => {
      if (typeof content === 'string') return _originalCreateFollowup(content);
      if (content.components) {
        addCommandIdToComponentCustomIds(content.components, ctx.state.id);
      }
      return _originalCreateFollowup(content);
    };
  }
  return [interaction, ctx as CommandContext];
}

function validateCustomIdLength(customId: string) {
  if (customId.length > 80) {
    throw new Error(`Custom ID too long: ${customId.length} characters (max 80) with this framework. Consider using shorter IDs.`);
  }
}

function addCommandIdToComponentCustomIds(components: Component[], commandId: string) {
  components.forEach((component) => {
    if (!component) return;
    if ('custom_id' in component) {
      validateCustomIdLength(component.custom_id as string);
      component.custom_id = `${component.custom_id}_${commandId}`;
    }
    if ('components' in component && Array.isArray(component.components)) {
      addCommandIdToComponentCustomIds(component.components, commandId);
    }
  });
}
