import { ButtonInteraction, StringSelectMenuInteraction, ModalSubmitInteraction, MessageFlags } from "discord.js";
 
import { UserError } from "@shared/lib/errors";
import { createErrorEmbed } from "@lib/embeds";
import { logger } from "@shared/lib/logger";

type ComponentInteraction = ButtonInteraction | StringSelectMenuInteraction | ModalSubmitInteraction;

/**
 * Handles component interactions (buttons, select menus, modals)
 * Routes to appropriate handlers based on customId patterns
 * Provides centralized error handling with UserError differentiation
 */
export class ComponentInteractionHandler {
    static async handle(interaction: ComponentInteraction): Promise<void> {
        const { interactionRoutes } = await import("@lib/interaction.routes");

        for (const route of interactionRoutes) {
            if (route.predicate(interaction)) {
                const module = await route.handler();
                const handlerMethod = module[route.method];

                if (typeof handlerMethod === 'function') {
                    try {
                        await handlerMethod(interaction);
                        return;
                    } catch (error) {
                        await this.handleError(interaction, error, route.method);
                        return;
                    }
                } else {
                    logger.error("bot", `Handler method ${route.method} not found in module`);
                }
            }
        }
    }

    /**
     * Handles errors from interaction handlers
     * Differentiates between UserError (user-facing) and system errors
     */
    private static async handleError(
        interaction: ComponentInteraction,
        error: unknown,
        handlerName: string
    ): Promise<void> {
        const isUserError = error instanceof UserError;

        // Determine error message
        const errorMessage = isUserError
            ? (error as Error).message
            : 'An unexpected error occurred. Please try again later.';

        // Log system errors (non-user errors) for debugging
        if (!isUserError) {
            logger.error("bot", `Error in ${handlerName}`, error);
        }

        const errorEmbed = createErrorEmbed(errorMessage);

        try {
            // Handle different interaction states
            if (interaction.replied || interaction.deferred) {
                await interaction.followUp({
                    embeds: [errorEmbed],
                    flags: MessageFlags.Ephemeral
                });
            } else {
                await interaction.reply({
                    embeds: [errorEmbed],
                    flags: MessageFlags.Ephemeral
                });
            }
        } catch (replyError) {
            // If we can't send a reply, log it
            logger.error("bot", `Failed to send error response in ${handlerName}`, replyError);
        }
    }
}
