import {
    type Interaction,
    ButtonInteraction,
    ModalSubmitInteraction,
    StringSelectMenuInteraction,
    ThreadChannel,
    TextChannel,
    EmbedBuilder
} from "discord.js";
import { tradeService } from "./trade.service";
import { inventoryService } from "@/modules/inventory/inventory.service";
import { createErrorEmbed, createWarningEmbed, createSuccessEmbed, createInfoEmbed } from "@lib/embeds";
import { UserError } from "@lib/errors";
import { getTradeDashboard, getTradeMoneyModal, getItemSelectMenu, getTradeCompletedEmbed } from "./trade.view";



export async function handleTradeInteraction(interaction: Interaction) {
    if (!interaction.isButton() && !interaction.isStringSelectMenu() && !interaction.isModalSubmit()) return;

    const { customId } = interaction;
    const threadId = interaction.channelId;

    if (!threadId) return;

    if (customId === 'trade_cancel') {
        await handleCancel(interaction, threadId);
    } else if (customId === 'trade_lock') {
        await handleLock(interaction, threadId);
    } else if (customId === 'trade_confirm') {
        // Confirm logic is handled implicitly by both locking or explicitly if needed.
        // For now, locking both triggers execution, so no separate confirm handler is actively used
        // unless we re-introduce a specific button. keeping basic handler stub if needed.
    } else if (customId === 'trade_add_money') {
        await handleAddMoneyClick(interaction);
    } else if (customId === 'trade_money_modal') {
        await handleMoneySubmit(interaction as ModalSubmitInteraction, threadId);
    } else if (customId === 'trade_add_item') {
        await handleAddItemClick(interaction as ButtonInteraction, threadId);
    } else if (customId === 'trade_select_item') {
        await handleItemSelect(interaction as StringSelectMenuInteraction, threadId);
    } else if (customId === 'trade_remove_item') {
        await handleRemoveItemClick(interaction as ButtonInteraction, threadId);
    } else if (customId === 'trade_remove_item_select') {
        await handleRemoveItemSelect(interaction as StringSelectMenuInteraction, threadId);
    }
}

async function handleCancel(interaction: ButtonInteraction | StringSelectMenuInteraction | ModalSubmitInteraction, threadId: string) {
    const session = tradeService.getSession(threadId);
    const user = interaction.user;

    tradeService.endSession(threadId);

    await interaction.deferUpdate();

    if (interaction.channel?.isThread()) {
        const embed = createInfoEmbed(`Trade cancelled by ${user.username}.`, "Trade Cancelled");
        await scheduleThreadCleanup(interaction.channel, "This thread will be deleted in 5 seconds.", 5000, embed);
    }
}

async function handleLock(interaction: ButtonInteraction | StringSelectMenuInteraction | ModalSubmitInteraction, threadId: string) {
    await interaction.deferUpdate();
    const isLocked = tradeService.toggleLock(threadId, interaction.user.id);
    await updateTradeDashboard(interaction, threadId);

    // Check if trade executed (both locked)
    const session = tradeService.getSession(threadId);
    if (session && session.state === 'COMPLETED') {
        // Trade executed during updateTradeDashboard
        return;
    }

    await interaction.followUp({ content: isLocked ? "🔒 You locked your offer." : "� You unlocked your offer.", ephemeral: true });
}

async function handleAddMoneyClick(interaction: Interaction) {
    if (!interaction.isButton()) return;
    const modal = getTradeMoneyModal();
    await interaction.showModal(modal);
}

async function handleMoneySubmit(interaction: ModalSubmitInteraction, threadId: string) {
    const amountStr = interaction.fields.getTextInputValue('amount');
    const amount = BigInt(amountStr);

    if (amount < 0n) throw new UserError("Amount must be positive");

    tradeService.updateMoney(threadId, interaction.user.id, amount);
    await interaction.deferUpdate(); // Acknowledge modal
    await updateTradeDashboard(interaction, threadId);
}

async function handleAddItemClick(interaction: ButtonInteraction, threadId: string) {
    const inventory = await inventoryService.getInventory(interaction.user.id);

    if (inventory.length === 0) {
        await interaction.reply({ embeds: [createWarningEmbed("Your inventory is empty.")], ephemeral: true });
        return;
    }

    // Slice top 25 for select menu
    const options = inventory.slice(0, 25).map(entry => ({
        label: `${entry.item.name} (${entry.quantity})`,
        value: entry.item.id.toString(),
        description: `Rarity: ${entry.item.rarity} `
    }));

    const { components } = getItemSelectMenu(options, 'trade_select_item', 'Select an item to add');
    await interaction.reply({ content: "Select an item to add:", components, ephemeral: true });
}

async function handleItemSelect(interaction: StringSelectMenuInteraction, threadId: string) {
    const value = interaction.values[0];
    if (!value) return;
    const itemId = parseInt(value);

    // Assuming implementation implies adding 1 item for now
    const item = await inventoryService.getItem(itemId);
    if (!item) throw new UserError("Item not found");

    tradeService.addItem(threadId, interaction.user.id, { id: item.id, name: item.name }, 1n);

    await interaction.update({ content: `Added ${item.name} x1`, components: [] });
    await updateTradeDashboard(interaction, threadId);
}

async function handleRemoveItemClick(interaction: ButtonInteraction, threadId: string) {
    const session = tradeService.getSession(threadId);
    if (!session) return;

    const participant = session.userA.id === interaction.user.id ? session.userA : session.userB;

    if (participant.offer.items.length === 0) {
        await interaction.reply({ embeds: [createWarningEmbed("No items in offer to remove.")], ephemeral: true });
        return;
    }

    const options = participant.offer.items.slice(0, 25).map(i => ({
        label: `${i.name} (${i.quantity})`,
        value: i.id.toString(),
    }));

    const { components } = getItemSelectMenu(options, 'trade_remove_item_select', 'Select an item to remove');
    await interaction.reply({ content: "Select an item to remove:", components, ephemeral: true });
}

async function handleRemoveItemSelect(interaction: StringSelectMenuInteraction, threadId: string) {
    const value = interaction.values[0];
    if (!value) return;
    const itemId = parseInt(value);
    tradeService.removeItem(threadId, interaction.user.id, itemId);

    await interaction.update({ content: `Removed item.`, components: [] });
    await updateTradeDashboard(interaction, threadId);
}


// --- DASHBOARD UPDATER ---

export async function updateTradeDashboard(interaction: Interaction, threadId: string) {
    const session = tradeService.getSession(threadId);
    if (!session) return;

    // Check Auto-Execute (If both locked)
    if (session.userA.locked && session.userB.locked) {
        // Execute Trade
        try {
            await tradeService.executeTrade(threadId);
            const embed = getTradeCompletedEmbed(session);
            await updateDashboardMessage(interaction, { embeds: [embed], components: [] });

            // Notify and Schedule Cleanup
            if (interaction.channel?.isThread()) {
                const successEmbed = createSuccessEmbed("Trade executed successfully. Items and funds have been transferred.", "Trade Complete");
                await scheduleThreadCleanup(
                    interaction.channel,
                    `🎉 Trade successful! < @${session.userA.id}> <@${session.userB.id}>\nThis thread will be deleted in 10 seconds.`,
                    10000,
                    successEmbed
                );
            }
            return;
        } catch (e: any) {
            console.error("Trade Execution Error:", e);
            const errorEmbed = createErrorEmbed(e.message, "Trade Failed");

            if (interaction.channel?.isThread()) {
                await scheduleThreadCleanup(
                    interaction.channel,
                    "❌ Trade failed due to an error. This thread will be deleted in 10 seconds.",
                    10000,
                    errorEmbed
                );
            }
            return;
        }
    }

    // Build Status Embed
    const { embeds, components } = getTradeDashboard(session);
    await updateDashboardMessage(interaction, { embeds, components });
}

async function updateDashboardMessage(interaction: Interaction, payload: any) {
    if (interaction.isButton() && interaction.message) {
        // If interaction came from the dashboard itself, we can edit directly
        try {
            await interaction.message.edit(payload);
        } catch (e) {
            console.error("Failed to edit message directly", e);
        }
    } else {
        // Find dashboard in channel
        const channel = interaction.channel as ThreadChannel;
        if (channel && channel.isThread()) {
            try {
                const messages = await channel.messages.fetch({ limit: 10 });
                const dashboardFn = messages.find(m => m.embeds[0]?.title === "🤝 Trading Session");
                if (dashboardFn) {
                    await dashboardFn.edit(payload);
                }
            } catch (e) {
                console.error("Failed to fetch/edit dashboard", e);
            }
        }
    }
}



async function scheduleThreadCleanup(channel: ThreadChannel | TextChannel, message: string, delayMs: number = 10000, embed?: EmbedBuilder) {
    try {
        const payload: any = { content: message };
        if (embed) payload.embeds = [embed];

        await channel.send(payload);

        setTimeout(async () => {
            try {
                if (channel.isThread()) {
                    console.log(`Deleting thread: ${channel.id} `);
                    await channel.delete("Trade Session Ended");
                }
            } catch (e) {
                console.error("Failed to delete thread", e);
            }
        }, delayMs);
    } catch (e) {
        console.error("Failed to send cleanup notification", e);
    }
}
