import { createCommand } from "@shared/lib/utils";
import {
    SlashCommandBuilder,
    type BaseGuildTextChannel,
    PermissionFlagsBits,
    MessageFlags
} from "discord.js";
import { inventoryService } from "@shared/modules/inventory/inventory.service";
import { createErrorEmbed } from "@lib/embeds";
import { items } from "@db/schema";
import { ilike, isNotNull, and, inArray } from "drizzle-orm";
import { DrizzleClient } from "@shared/db/DrizzleClient";
import { getShopListingMessage } from "@/modules/economy/shop.view";
import { EffectType, LootType } from "@shared/lib/constants";
import { withCommandErrorHandling } from "@lib/commandUtils";

export const listing = createCommand({
    data: new SlashCommandBuilder()
        .setName("listing")
        .setDescription("Post an item listing in the channel for users to buy")
        .addNumberOption(option =>
            option.setName("item")
                .setDescription("The item to list")
                .setRequired(true)
                .setAutocomplete(true)
        )
        .addChannelOption(option =>
            option.setName("channel")
                .setDescription("The channel to post the listing in (defaults to current)")
                .setRequired(false)
        )
        .setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
    execute: async (interaction) => {
        await withCommandErrorHandling(
            interaction,
            async () => {
                const itemId = interaction.options.getNumber("item", true);
                const targetChannel = (interaction.options.getChannel("channel") as BaseGuildTextChannel) || interaction.channel as BaseGuildTextChannel;

                if (!targetChannel || !targetChannel.isSendable()) {
                    await interaction.editReply({ content: "", embeds: [createErrorEmbed("Target channel is invalid or not sendable.")] });
                    return;
                }

                const item = await inventoryService.getItem(itemId);
                if (!item) {
                    await interaction.editReply({ content: "", embeds: [createErrorEmbed(`Item with ID ${itemId} not found.`)] });
                    return;
                }

                if (!item.price) {
                    await interaction.editReply({ content: "", embeds: [createErrorEmbed(`Item "${item.name}" is not for sale (no price set).`)] });
                    return;
                }

                // Prepare context for lootboxes
                const context: { referencedItems: Map<number, { name: string; rarity: string }> } = { referencedItems: new Map() };

                const usageData = item.usageData as any;
                const lootboxEffect = usageData?.effects?.find((e: any) => e.type === EffectType.LOOTBOX);

                if (lootboxEffect && lootboxEffect.pool) {
                    const itemIds = lootboxEffect.pool
                        .filter((drop: any) => drop.type === LootType.ITEM && drop.itemId)
                        .map((drop: any) => drop.itemId);

                    if (itemIds.length > 0) {
                        // Remove duplicates
                        const uniqueIds = [...new Set(itemIds)] as number[];

                        const referencedItems = await DrizzleClient.select({
                            id: items.id,
                            name: items.name,
                            rarity: items.rarity
                        }).from(items).where(inArray(items.id, uniqueIds));

                        for (const ref of referencedItems) {
                            context.referencedItems.set(ref.id, { name: ref.name, rarity: ref.rarity || 'C' });
                        }
                    }
                }

                const listingMessage = getShopListingMessage({
                    ...item,
                    rarity: item.rarity || undefined,
                    formattedPrice: `${item.price} 🪙`,
                    price: item.price
                }, context);

                await targetChannel.send(listingMessage as any);
                await interaction.editReply({ content: `✅ Listing for **${item.name}** posted in ${targetChannel}.` });
            },
            { ephemeral: true }
        );
    },
    autocomplete: async (interaction) => {
        const focusedValue = interaction.options.getFocused();

        const results = await DrizzleClient.select({
            id: items.id,
            name: items.name,
            price: items.price
        })
            .from(items)
            .where(
                and(
                    ilike(items.name, `%${focusedValue}%`),
                    isNotNull(items.price)
                )
            )
            .limit(20);

        await interaction.respond(
            results.map(item => ({
                name: `${item.name} (Price: ${item.price})`,
                value: item.id
            }))
        );
    }
});
