import {
    ActionRowBuilder,
    ButtonBuilder,
    ButtonStyle,
    AttachmentBuilder,
    ContainerBuilder,
    SectionBuilder,
    TextDisplayBuilder,
    MediaGalleryBuilder,
    MediaGalleryItemBuilder,
    ThumbnailBuilder,
    SeparatorBuilder,
    SeparatorSpacingSize,
    MessageFlags
} from "discord.js";
import { resolveAssetUrl, isLocalAssetUrl } from "@shared/lib/assets";
import { join } from "path";
import { existsSync } from "fs";
import { LootType, EffectType } from "@shared/lib/constants";
import type { LootTableItem } from "@shared/lib/types";
import { getRarityConfig, defaultName, stripQuery } from "@shared/lib/rarity";
import { SHOP_CUSTOM_IDS } from "./economy.types";

export function getShopListingMessage(
    item: {
        id: number;
        name: string;
        description: string | null;
        formattedPrice: string;
        iconUrl: string | null;
        imageUrl: string | null;
        price: number | bigint;
        usageData?: any;
        rarity?: string;
    },
    context?: { referencedItems: Map<number, { name: string; rarity: string }> }
) {
    const files: AttachmentBuilder[] = [];
    let thumbnailUrl = resolveAssetUrl(item.iconUrl);
    let displayImageUrl = resolveAssetUrl(item.imageUrl);

    // Handle local icon
    if (item.iconUrl && isLocalAssetUrl(item.iconUrl)) {
        const iconPath = join(process.cwd(), "bot/assets/graphics", stripQuery(item.iconUrl).replace(/^\/?assets\//, ""));
        if (existsSync(iconPath)) {
            const iconName = defaultName(item.iconUrl);
            files.push(new AttachmentBuilder(iconPath, { name: iconName }));
            thumbnailUrl = `attachment://${iconName}`;
        }
    }

    // Handle local image
    if (item.imageUrl && isLocalAssetUrl(item.imageUrl)) {
        if (item.imageUrl === item.iconUrl && thumbnailUrl?.startsWith("attachment://")) {
            displayImageUrl = thumbnailUrl;
        } else {
            const imagePath = join(process.cwd(), "bot/assets/graphics", stripQuery(item.imageUrl).replace(/^\/?assets\//, ""));
            if (existsSync(imagePath)) {
                const imageName = defaultName(item.imageUrl);
                if (!files.find(f => f.name === imageName)) {
                    files.push(new AttachmentBuilder(imagePath, { name: imageName }));
                }
                displayImageUrl = `attachment://${imageName}`;
            }
        }
    }

    const containers: ContainerBuilder[] = [];

    // 1. Main Container
    const mainContainer = new ContainerBuilder()
        .setAccentColor(getRarityConfig(item.rarity || "C").color);

    // Header Section
    const infoSection = new SectionBuilder()
        .addTextDisplayComponents(
            new TextDisplayBuilder().setContent(`# ${item.name}`),
            new TextDisplayBuilder().setContent(item.description || "_No description available._"),
            new TextDisplayBuilder().setContent(`### 🏷️ Price: ${item.formattedPrice}`)
        );

    // Set Thumbnail Accessory if we have an icon
    if (thumbnailUrl) {
        infoSection.setThumbnailAccessory(new ThumbnailBuilder().setURL(thumbnailUrl));
    }

    mainContainer.addSectionComponents(infoSection);

    // Media Gallery for additional images (if multiple)
    const mediaSources: string[] = [];
    if (thumbnailUrl) mediaSources.push(thumbnailUrl);
    if (displayImageUrl && displayImageUrl !== thumbnailUrl) mediaSources.push(displayImageUrl);

    if (mediaSources.length > 1) {
        mainContainer.addMediaGalleryComponents(
            new MediaGalleryBuilder().addItems(
                ...mediaSources.map(src => new MediaGalleryItemBuilder().setURL(src))
            )
        );
    }

    // Create buy button (used in either main or loot container)
    const buyButton = new ButtonBuilder()
        .setCustomId(SHOP_CUSTOM_IDS.BUY(item.id))
        .setLabel(`Purchase for ${item.price} 🪙`)
        .setStyle(ButtonStyle.Success)
        .setEmoji("🛒");

    // 2. Loot Table (if applicable) — separate Container with blurple accent
    const lootboxEffect = item.usageData?.effects?.find((e: any) => e.type === EffectType.LOOTBOX);
    if (lootboxEffect) {
        const pool = lootboxEffect.pool as LootTableItem[];
        const totalWeight = pool.reduce((sum: number, i: LootTableItem) => sum + i.weight, 0);

        const lootContainer = new ContainerBuilder().setAccentColor(0x5865F2);
        lootContainer.addTextDisplayComponents(
            new TextDisplayBuilder().setContent("## 🎁 Loot Table")
        );

        // Group drops by rarity tier with aggregated percentages
        const tiers: Record<string, { items: string[]; totalChance: number }> = {};

        for (const drop of pool) {
            const chance = (drop.weight / totalWeight) * 100;
            let line = "";
            let rarity = "C";

            switch (drop.type as any) {
                case LootType.CURRENCY: {
                    const amt = (drop.minAmount != null && drop.maxAmount != null)
                        ? `${drop.minAmount} – ${drop.maxAmount}`
                        : (Array.isArray(drop.amount) ? `${drop.amount[0]} – ${drop.amount[1]}` : `${drop.amount || 0}`);
                    line = `${amt} 🪙`;
                    rarity = "CURRENCY";
                    break;
                }
                case LootType.XP: {
                    const amt = (drop.minAmount != null && drop.maxAmount != null)
                        ? `${drop.minAmount} – ${drop.maxAmount}`
                        : (Array.isArray(drop.amount) ? `${drop.amount[0]} – ${drop.amount[1]}` : `${drop.amount || 0}`);
                    line = `${amt} XP`;
                    rarity = "XP";
                    break;
                }
                case LootType.ITEM: {
                    const referencedItems = context?.referencedItems;
                    if (drop.itemId && referencedItems?.has(drop.itemId)) {
                        const i = referencedItems.get(drop.itemId)!;
                        line = `${i.name} ×${drop.amount || 1}`;
                        rarity = i.rarity;
                    } else {
                        line = `Unknown Item`;
                        rarity = "C";
                    }
                    break;
                }
                case LootType.NOTHING: {
                    line = "Nothing";
                    rarity = "NOTHING";
                    break;
                }
            }

            if (line) {
                if (!tiers[rarity]) tiers[rarity] = { items: [], totalChance: 0 };
                tiers[rarity].items.push(line);
                tiers[rarity].totalChance += chance;
            }
        }

        const order = ["SSR", "SR", "R", "C", "CURRENCY", "XP", "NOTHING"];
        let isFirst = true;
        for (const rarity of order) {
            const tier = tiers[rarity];
            if (!tier || tier.items.length === 0) continue;

            if (!isFirst) {
                lootContainer.addSeparatorComponents(
                    new SeparatorBuilder().setSpacing(SeparatorSpacingSize.Small)
                );
            }
            isFirst = false;

            const config = getRarityConfig(rarity);
            const chanceStr = tier.totalChance < 0.1 ? "<0.1" : tier.totalChance.toFixed(1);
            lootContainer.addTextDisplayComponents(
                new TextDisplayBuilder().setContent(
                    `${config.emoji} **${config.label}** — ${chanceStr}%`
                ),
                new TextDisplayBuilder().setContent(tier.items.join(", "))
            );
        }

        // Purchase button inside loot table container
        lootContainer.addActionRowComponents(
            new ActionRowBuilder<ButtonBuilder>().addComponents(buyButton)
        );

        containers.push(mainContainer);
        containers.push(lootContainer);
    } else {
        // Non-lootbox items: purchase button stays in main container
        mainContainer.addActionRowComponents(
            new ActionRowBuilder<ButtonBuilder>().addComponents(buyButton)
        );

        containers.push(mainContainer);
    }

    return {
        components: containers as any,
        files,
        flags: MessageFlags.IsComponentsV2
    };
}
