import { createCommand } from "@shared/lib/utils";
import { SlashCommandBuilder, PermissionFlagsBits, Colors, userMention, roleMention, ChatInputCommandInteraction } from "discord.js";
import { featureFlagsService } from "@shared/modules/feature-flags/feature-flags.service";
import { createBaseEmbed, createErrorEmbed, createSuccessEmbed } from "@lib/embeds";
import { withCommandErrorHandling } from "@lib/commandUtils";

export const featureflags = createCommand({
    data: new SlashCommandBuilder()
        .setName("featureflags")
        .setDescription("Manage feature flags for beta testing")
        .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
        .addSubcommand(sub =>
            sub.setName("list")
                .setDescription("List all feature flags")
        )
        .addSubcommand(sub =>
            sub.setName("create")
                .setDescription("Create a new feature flag")
                .addStringOption(opt =>
                    opt.setName("name")
                        .setDescription("Name of the feature flag")
                        .setRequired(true)
                )
                .addStringOption(opt =>
                    opt.setName("description")
                        .setDescription("Description of the feature flag")
                        .setRequired(false)
                )
        )
        .addSubcommand(sub =>
            sub.setName("delete")
                .setDescription("Delete a feature flag")
                .addStringOption(opt =>
                    opt.setName("name")
                        .setDescription("Name of the feature flag")
                        .setRequired(true)
                        .setAutocomplete(true)
                )
        )
        .addSubcommand(sub =>
            sub.setName("enable")
                .setDescription("Enable a feature flag")
                .addStringOption(opt =>
                    opt.setName("name")
                        .setDescription("Name of the feature flag")
                        .setRequired(true)
                        .setAutocomplete(true)
                )
        )
        .addSubcommand(sub =>
            sub.setName("disable")
                .setDescription("Disable a feature flag")
                .addStringOption(opt =>
                    opt.setName("name")
                        .setDescription("Name of the feature flag")
                        .setRequired(true)
                        .setAutocomplete(true)
                )
        )
        .addSubcommand(sub =>
            sub.setName("grant")
                .setDescription("Grant access to a feature flag")
                .addStringOption(opt =>
                    opt.setName("name")
                        .setDescription("Name of the feature flag")
                        .setRequired(true)
                        .setAutocomplete(true)
                )
                .addUserOption(opt =>
                    opt.setName("user")
                        .setDescription("User to grant access to")
                        .setRequired(false)
                )
                .addRoleOption(opt =>
                    opt.setName("role")
                        .setDescription("Role to grant access to")
                        .setRequired(false)
                )
        )
        .addSubcommand(sub =>
            sub.setName("revoke")
                .setDescription("Revoke access from a feature flag")
                .addIntegerOption(opt =>
                    opt.setName("id")
                        .setDescription("Access record ID to revoke")
                        .setRequired(true)
                )
        )
        .addSubcommand(sub =>
            sub.setName("access")
                .setDescription("List access records for a feature flag")
                .addStringOption(opt =>
                    opt.setName("name")
                        .setDescription("Name of the feature flag")
                        .setRequired(true)
                        .setAutocomplete(true)
                )
        ),
    autocomplete: async (interaction) => {
        const focused = interaction.options.getFocused(true);

        if (focused.name === "name") {
            const flags = await featureFlagsService.listFlags();
            const filtered = flags
                .filter(f => f.name.toLowerCase().includes(focused.value.toLowerCase()))
                .slice(0, 25);

            await interaction.respond(
                filtered.map(f => ({ name: `${f.name} (${f.enabled ? "enabled" : "disabled"})`, value: f.name }))
            );
        }
    },
    execute: async (interaction) => {
        await withCommandErrorHandling(
            interaction,
            async () => {
                const subcommand = interaction.options.getSubcommand();

                switch (subcommand) {
                    case "list":
                        await handleList(interaction);
                        break;
                    case "create":
                        await handleCreate(interaction);
                        break;
                    case "delete":
                        await handleDelete(interaction);
                        break;
                    case "enable":
                        await handleEnable(interaction);
                        break;
                    case "disable":
                        await handleDisable(interaction);
                        break;
                    case "grant":
                        await handleGrant(interaction);
                        break;
                    case "revoke":
                        await handleRevoke(interaction);
                        break;
                    case "access":
                        await handleAccess(interaction);
                        break;
                }
            },
            { ephemeral: true }
        );
    },
});

async function handleList(interaction: ChatInputCommandInteraction) {
    const flags = await featureFlagsService.listFlags();

    if (flags.length === 0) {
        await interaction.editReply({ embeds: [createBaseEmbed("Feature Flags", "No feature flags have been created yet.", Colors.Blue)] });
        return;
    }

    const embed = createBaseEmbed("Feature Flags", undefined, Colors.Blue)
        .addFields(
            flags.map(f => ({
                name: f.name,
                value: `${f.enabled ? "✅ Enabled" : "❌ Disabled"}\n${f.description || "*No description*"}`,
                inline: false,
            }))
        );

    await interaction.editReply({ embeds: [embed] });
}

async function handleCreate(interaction: ChatInputCommandInteraction) {
    const name = interaction.options.getString("name", true);
    const description = interaction.options.getString("description");

    const flag = await featureFlagsService.createFlag(name, description ?? undefined);

    if (!flag) {
        await interaction.editReply({ embeds: [createErrorEmbed("Failed to create feature flag.")] });
        return;
    }

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Feature flag "**${flag.name}**" created successfully. Use \`/featureflags enable\` to enable it.`)]
    });
}

async function handleDelete(interaction: ChatInputCommandInteraction) {
    const name = interaction.options.getString("name", true);

    const flag = await featureFlagsService.deleteFlag(name);

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Feature flag "**${flag.name}**" has been deleted.`)]
    });
}

async function handleEnable(interaction: ChatInputCommandInteraction) {
    const name = interaction.options.getString("name", true);

    const flag = await featureFlagsService.setFlagEnabled(name, true);

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Feature flag "**${flag.name}**" has been enabled.`)]
    });
}

async function handleDisable(interaction: ChatInputCommandInteraction) {
    const name = interaction.options.getString("name", true);

    const flag = await featureFlagsService.setFlagEnabled(name, false);

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Feature flag "**${flag.name}**" has been disabled.`)]
    });
}

async function handleGrant(interaction: ChatInputCommandInteraction) {
    const name = interaction.options.getString("name", true);
    const user = interaction.options.getUser("user");
    const role = interaction.options.getRole("role");

    if (!user && !role) {
        await interaction.editReply({
            embeds: [createErrorEmbed("You must specify either a user or a role to grant access to.")]
        });
        return;
    }

    const access = await featureFlagsService.grantAccess(name, {
        userId: user?.id,
        roleId: role?.id,
        guildId: interaction.guildId!,
    });

    if (!access) {
        await interaction.editReply({ embeds: [createErrorEmbed("Failed to grant access.")] });
        return;
    }

    let target: string;
    if (user) {
        target = userMention(user.id);
    } else if (role) {
        target = roleMention(role.id);
    } else {
        target = "Unknown";
    }

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Access to "**${name}**" granted to ${target} (ID: ${access.id})`)]
    });
}

async function handleRevoke(interaction: ChatInputCommandInteraction) {
    const id = interaction.options.getInteger("id", true);

    const access = await featureFlagsService.revokeAccess(id);

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Access record #${access.id} has been revoked.`)]
    });
}

async function handleAccess(interaction: ChatInputCommandInteraction) {
    const name = interaction.options.getString("name", true);

    const accessRecords = await featureFlagsService.listAccess(name);

    if (accessRecords.length === 0) {
        await interaction.editReply({
            embeds: [createBaseEmbed("Feature Flag Access", `No access records for "**${name}**".`, Colors.Blue)]
        });
        return;
    }

    const fields = accessRecords.map(a => {
        let target = "Unknown";
        if (a.userId) target = `User: ${userMention(a.userId.toString())}`;
        else if (a.roleId) target = `Role: ${roleMention(a.roleId.toString())}`;
        else if (a.guildId) target = `Guild: ${a.guildId.toString()}`;

        return {
            name: `ID: ${a.id}`,
            value: target,
            inline: true,
        };
    });

    const embed = createBaseEmbed(`Feature Flag Access: ${name}`, undefined, Colors.Blue)
        .addFields(fields);

    await interaction.editReply({ embeds: [embed] });
}
