import { createCommand } from "@shared/lib/utils";
import { SlashCommandBuilder, PermissionFlagsBits, Colors, ChatInputCommandInteraction } from "discord.js";
import { guildSettingsService } from "@shared/modules/guild-settings/guild-settings.service";
import { createBaseEmbed, createErrorEmbed, createSuccessEmbed } from "@lib/embeds";
import { getGuildConfig, invalidateGuildConfigCache } from "@shared/lib/config";
import { withCommandErrorHandling } from "@lib/commandUtils";

export const settings = createCommand({
    data: new SlashCommandBuilder()
        .setName("settings")
        .setDescription("Manage guild settings")
        .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
        .addSubcommand(sub =>
            sub.setName("show")
                .setDescription("Show current guild settings"))
        .addSubcommand(sub =>
            sub.setName("set")
                .setDescription("Set a guild setting")
                .addStringOption(opt =>
                    opt.setName("key")
                        .setDescription("Setting to change")
                        .setRequired(true)
                        .addChoices(
                            { name: "Student Role", value: "studentRole" },
                            { name: "Visitor Role", value: "visitorRole" },
                            { name: "Welcome Channel", value: "welcomeChannel" },
                            { name: "Welcome Message", value: "welcomeMessage" },
                            { name: "Feedback Channel", value: "feedbackChannel" },
                            { name: "Terminal Channel", value: "terminalChannel" },
                            { name: "Terminal Message", value: "terminalMessage" },
                            { name: "Moderation Log Channel", value: "moderationLogChannel" },
                            { name: "DM on Warn", value: "moderationDmOnWarn" },
                            { name: "Auto Timeout Threshold", value: "moderationAutoTimeoutThreshold" },
                        ))
                .addRoleOption(opt =>
                    opt.setName("role")
                        .setDescription("Role value"))
                .addChannelOption(opt =>
                    opt.setName("channel")
                        .setDescription("Channel value"))
                .addStringOption(opt =>
                    opt.setName("text")
                        .setDescription("Text value"))
                .addIntegerOption(opt =>
                    opt.setName("number")
                        .setDescription("Number value"))
                .addBooleanOption(opt =>
                    opt.setName("boolean")
                        .setDescription("Boolean value (true/false)")))
        .addSubcommand(sub =>
            sub.setName("reset")
                .setDescription("Reset a setting to default")
                .addStringOption(opt =>
                    opt.setName("key")
                        .setDescription("Setting to reset")
                        .setRequired(true)
                        .addChoices(
                            { name: "Student Role", value: "studentRole" },
                            { name: "Visitor Role", value: "visitorRole" },
                            { name: "Welcome Channel", value: "welcomeChannel" },
                            { name: "Welcome Message", value: "welcomeMessage" },
                            { name: "Feedback Channel", value: "feedbackChannel" },
                            { name: "Terminal Channel", value: "terminalChannel" },
                            { name: "Terminal Message", value: "terminalMessage" },
                            { name: "Moderation Log Channel", value: "moderationLogChannel" },
                            { name: "DM on Warn", value: "moderationDmOnWarn" },
                            { name: "Auto Timeout Threshold", value: "moderationAutoTimeoutThreshold" },
                        )))
        .addSubcommand(sub =>
            sub.setName("colors")
                .setDescription("Manage color roles")
                .addStringOption(opt =>
                    opt.setName("action")
                        .setDescription("Action to perform")
                        .setRequired(true)
                        .addChoices(
                            { name: "List", value: "list" },
                            { name: "Add", value: "add" },
                            { name: "Remove", value: "remove" },
                        ))
                .addRoleOption(opt =>
                    opt.setName("role")
                        .setDescription("Role to add/remove")
                        .setRequired(false))),

    execute: async (interaction) => {
        await withCommandErrorHandling(
            interaction,
            async () => {
                const subcommand = interaction.options.getSubcommand();
                const guildId = interaction.guildId!;

                switch (subcommand) {
                    case "show":
                        await handleShow(interaction, guildId);
                        break;
                    case "set":
                        await handleSet(interaction, guildId);
                        break;
                    case "reset":
                        await handleReset(interaction, guildId);
                        break;
                    case "colors":
                        await handleColors(interaction, guildId);
                        break;
                }
            },
            { ephemeral: true }
        );
    },
});

async function handleShow(interaction: ChatInputCommandInteraction, guildId: string) {
    const settings = await getGuildConfig(guildId);

    const colorRolesDisplay = settings.colorRoles?.length
        ? settings.colorRoles.map(id => `<@&${id}>`).join(", ")
        : "None";

    const embed = createBaseEmbed("Guild Settings", undefined, Colors.Blue)
        .addFields(
            { name: "Student Role", value: settings.studentRole ? `<@&${settings.studentRole}>` : "Not set", inline: true },
            { name: "Visitor Role", value: settings.visitorRole ? `<@&${settings.visitorRole}>` : "Not set", inline: true },
            { name: "\u200b", value: "\u200b", inline: true },
            { name: "Welcome Channel", value: settings.welcomeChannelId ? `<#${settings.welcomeChannelId}>` : "Not set", inline: true },
            { name: "Feedback Channel", value: settings.feedbackChannelId ? `<#${settings.feedbackChannelId}>` : "Not set", inline: true },
            { name: "Moderation Log", value: settings.moderation?.cases?.logChannelId ? `<#${settings.moderation.cases.logChannelId}>` : "Not set", inline: true },
            { name: "Terminal Channel", value: settings.terminal?.channelId ? `<#${settings.terminal.channelId}>` : "Not set", inline: true },
            { name: "DM on Warn", value: settings.moderation?.cases?.dmOnWarn !== false ? "Enabled" : "Disabled", inline: true },
            { name: "Auto Timeout", value: settings.moderation?.cases?.autoTimeoutThreshold ? `${settings.moderation.cases.autoTimeoutThreshold} warnings` : "Disabled", inline: true },
            { name: "Color Roles", value: colorRolesDisplay, inline: false },
        );

    if (settings.welcomeMessage) {
        embed.addFields({ name: "Welcome Message", value: settings.welcomeMessage.substring(0, 1024), inline: false });
    }

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

async function handleSet(interaction: ChatInputCommandInteraction, guildId: string) {
    const key = interaction.options.getString("key", true);
    const role = interaction.options.getRole("role");
    const channel = interaction.options.getChannel("channel");
    const text = interaction.options.getString("text");
    const number = interaction.options.getInteger("number");
    const boolean = interaction.options.getBoolean("boolean");

    let value: string | number | boolean | null = null;

    if (role) value = role.id;
    else if (channel) value = channel.id;
    else if (text) value = text;
    else if (number !== null) value = number;
    else if (boolean !== null) value = boolean;

    if (value === null) {
        await interaction.editReply({
            embeds: [createErrorEmbed("Please provide a role, channel, text, number, or boolean value")]
        });
        return;
    }

    await guildSettingsService.updateSetting(guildId, key, value);
    invalidateGuildConfigCache(guildId);

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Setting "${key}" updated`)]
    });
}

async function handleReset(interaction: ChatInputCommandInteraction, guildId: string) {
    const key = interaction.options.getString("key", true);

    await guildSettingsService.updateSetting(guildId, key, null);
    invalidateGuildConfigCache(guildId);

    await interaction.editReply({
        embeds: [createSuccessEmbed(`Setting "${key}" reset to default`)]
    });
}

async function handleColors(interaction: ChatInputCommandInteraction, guildId: string) {
    const action = interaction.options.getString("action", true);
    const role = interaction.options.getRole("role");

    switch (action) {
        case "list": {
            const settings = await getGuildConfig(guildId);
            const colorRoles = settings.colorRoles ?? [];

            if (colorRoles.length === 0) {
                await interaction.editReply({
                    embeds: [createBaseEmbed("Color Roles", "No color roles configured.", Colors.Blue)]
                });
                return;
            }

            const embed = createBaseEmbed("Color Roles", undefined, Colors.Blue)
                .addFields({
                    name: `Configured Roles (${colorRoles.length})`,
                    value: colorRoles.map(id => `<@&${id}>`).join("\n"),
                });

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

        case "add": {
            if (!role) {
                await interaction.editReply({
                    embeds: [createErrorEmbed("Please specify a role to add.")]
                });
                return;
            }

            await guildSettingsService.addColorRole(guildId, role.id);
            invalidateGuildConfigCache(guildId);

            await interaction.editReply({
                embeds: [createSuccessEmbed(`Added <@&${role.id}> to color roles.`)]
            });
            break;
        }

        case "remove": {
            if (!role) {
                await interaction.editReply({
                    embeds: [createErrorEmbed("Please specify a role to remove.")]
                });
                return;
            }

            await guildSettingsService.removeColorRole(guildId, role.id);
            invalidateGuildConfigCache(guildId);

            await interaction.editReply({
                embeds: [createSuccessEmbed(`Removed <@&${role.id}> from color roles.`)]
            });
            break;
        }
    }
}
