import {
    ActionRowBuilder,
    ButtonBuilder,
    ButtonStyle,
    AttachmentBuilder,
    Colors,
    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";

// Rarity Color Map
const RarityColors: Record<string, number> = {
    "C": Colors.LightGrey,
    "R": Colors.Blue,
    "SR": Colors.Purple,
    "SSR": Colors.Gold,
    "CURRENCY": Colors.Green,
    "XP": Colors.Aqua,
    "NOTHING": Colors.DarkButNotBlack
};

const TitleMap: Record<string, string> = {
    "C": "📦 Common Items",
    "R": "📦 Rare Items",
    "SR": "✨ Super Rare Items",
    "SSR": "🌟 SSR Items",
    "CURRENCY": "💰 Currency",
    "XP": "🔮 Experience",
    "NOTHING": "💨 Empty"
};

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", 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", 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(RarityColors[item.rarity || "C"] || Colors.Green);

    // 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))
            )
        );
    }

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

        mainContainer.addSeparatorComponents(new SeparatorBuilder().setSpacing(SeparatorSpacingSize.Small));
        mainContainer.addTextDisplayComponents(new TextDisplayBuilder().setContent("## 🎁 Potential Rewards"));

        const groups: Record<string, string[]> = {};
        for (const drop of pool) {
            const chance = ((drop.weight / totalWeight) * 100).toFixed(1);
            let line = "";
            let rarity = "C";

            switch (drop.type as any) {
                case LootType.CURRENCY:
                    const currAmount = (drop.minAmount != null && drop.maxAmount != null)
                        ? `${drop.minAmount} - ${drop.maxAmount}`
                        : (Array.isArray(drop.amount) ? `${drop.amount[0]} - ${drop.amount[1]}` : drop.amount || 0);
                    line = `**${currAmount} 🪙** (${chance}%)`;
                    rarity = "CURRENCY";
                    break;
                case LootType.XP:
                    const xpAmount = (drop.minAmount != null && drop.maxAmount != null)
                        ? `${drop.minAmount} - ${drop.maxAmount}`
                        : (Array.isArray(drop.amount) ? `${drop.amount[0]} - ${drop.amount[1]}` : drop.amount || 0);
                    line = `**${xpAmount} XP** (${chance}%)`;
                    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}** x${drop.amount || 1} (${chance}%)`;
                        rarity = i.rarity;
                    } else {
                        line = `**Unknown Item** (${chance}%)`;
                        rarity = "C";
                    }
                    break;
                case LootType.NOTHING:
                    line = `**Nothing** (${chance}%)`;
                    rarity = "NOTHING";
                    break;
            }

            if (line) {
                if (!groups[rarity]) groups[rarity] = [];
                groups[rarity]!.push(line);
            }
        }

        const order = ["SSR", "SR", "R", "C", "CURRENCY", "XP", "NOTHING"];
        for (const rarity of order) {
            if (groups[rarity] && groups[rarity]!.length > 0) {
                mainContainer.addTextDisplayComponents(
                    new TextDisplayBuilder().setContent(`### ${TitleMap[rarity] || rarity}`),
                    new TextDisplayBuilder().setContent(groups[rarity]!.join("\n"))
                );
            }
        }
    }

    // Purchase Row
    const buyButton = new ButtonBuilder()
        .setCustomId(`shop_buy_${item.id}`)
        .setLabel(`Purchase for ${item.price} 🪙`)
        .setStyle(ButtonStyle.Success)
        .setEmoji("🛒");

    mainContainer.addActionRowComponents(
        new ActionRowBuilder<ButtonBuilder>().addComponents(buyButton)
    );

    containers.push(mainContainer);

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

function defaultName(path: string): string {
    return path.split("/").pop() || "image.png";
}
