/**
 * Galaxy Strike Online — Server Item System
 * All item/shop data comes from ContentLoader (data/gso/items/).
 * No hardcoded item data lives here.
 */

class ItemSystem {
    constructor(contentLoader = null) {
        this.serverUrl = process.env.SERVER_URL || 'http://localhost:3002';
        this._loader   = contentLoader;

        if (contentLoader) {
            console.log(`[ITEM SYSTEM] ${contentLoader.items.size} items available from ContentLoader`);
        } else {
            console.warn('[ITEM SYSTEM] No ContentLoader provided — item catalog is empty');
        }
    }

    setServerUrl(url) { this.serverUrl = url; }

    // ── Catalog access ─────────────────────────────────────────────────────

    getAllItems()         { return this._loader ? this._loader.getAllItems()    : []; }
    getItem(id)          { return this._loader ? this._loader.getItem(id)      : null; }
    getItemsByType(type) { return this._loader ? this._loader.getItemsByType(type) : []; }

    /**
     * Returns all items that include 'shop' in their categories array.
     * Grouped by item type: { ship: [...], weapon: [...], ... }
     */
    getShopItemsByCategory() {
        const out = {};
        for (const item of this.getAllItems()) {
            if (!Array.isArray(item.categories) || !item.categories.includes('shop')) continue;
            const t = item.type || 'misc';
            if (!out[t]) out[t] = [];
            out[t].push(this._normaliseForClient(item));
        }
        return out;
    }

    /**
     * Flat array of all shop items.
     * Called as getRandomShopItems() by legacy server.js code — returns the same thing,
     * just grouped (matching the expected { category: [items] } shape).
     */
    getRandomShopItems() {
        return this.getShopItemsByCategory();
    }

    /**
     * All shop items for a single type/category.
     * Called as getRandomItemsByCategory(category) by legacy server.js code.
     */
    getRandomItemsByCategory(category) {
        return this.getAllItems()
            .filter(i =>
                Array.isArray(i.categories) && i.categories.includes('shop') &&
                i.type === category
            )
            .map(i => this._normaliseForClient(i));
    }

    // ── Shop helpers ───────────────────────────────────────────────────────

    /**
     * Find an item that is available in the shop.
     * Returns null if the item doesn't exist or isn't in the shop.
     */
    findShopItem(itemId) {
        const item = this.getItem(itemId);
        if (!item) return null;
        if (!Array.isArray(item.categories) || !item.categories.includes('shop')) return null;
        return item;
    }

    /**
     * Validate a purchase against player wallet.
     * Returns { valid: true } or { valid: false, error: '...' }
     */
    validatePurchase(item, playerStats, quantity = 1) {
        const currency  = item.currency || 'credits';
        const totalCost = (item.price || 0) * quantity;

        if (currency === 'credits' && (playerStats.credits || 0) < totalCost) {
            return { valid: false, error: 'Not enough credits' };
        }
        if (currency === 'gems' && (playerStats.gems || 0) < totalCost) {
            return { valid: false, error: 'Not enough gems' };
        }
        return { valid: true, totalCost, currency };
    }

    /**
     * Apply a purchase to playerData (mutates directly, like the original server did).
     * Returns the purchase summary for the response payload.
     */
    applyPurchase(item, playerData, quantity = 1) {
        const currency  = item.currency || 'credits';
        const totalCost = (item.price || 0) * quantity;

        // Deduct currency
        if (currency === 'credits') playerData.stats.credits = (playerData.stats.credits || 0) - totalCost;
        if (currency === 'gems')    playerData.stats.gems    = (playerData.stats.gems    || 0) - totalCost;

        // Grant item
        switch (item.type) {
            case 'decoration':
                if (!playerData.starbase) playerData.starbase = { wallpaper: null, ownedWallpapers: [], unlockedRooms: [] };
                if (item.subtype === 'wallpaper') {
                    if (!playerData.starbase.ownedWallpapers) playerData.starbase.ownedWallpapers = [];
                    if (!playerData.starbase.ownedWallpapers.includes(item.id)) {
                        playerData.starbase.ownedWallpapers.push(item.id);
                    }
                } else if (item.subtype === 'room_unlock') {
                    if (!playerData.starbase.unlockedRooms) playerData.starbase.unlockedRooms = [];
                    if (item.roomId && !playerData.starbase.unlockedRooms.includes(item.roomId)) {
                        playerData.starbase.unlockedRooms.push(item.roomId);
                    }
                }
                break;

            case 'ship':
                if (!playerData.ownedShips) playerData.ownedShips = [];
                if (!playerData.ownedShips.includes(item.id)) playerData.ownedShips.push(item.id);
                break;

            case 'cosmetic':
                if (!playerData.ownedCosmetics) playerData.ownedCosmetics = [];
                if (!playerData.ownedCosmetics.includes(item.id)) playerData.ownedCosmetics.push(item.id);
                break;

            case 'weapon':
            case 'armour':
            case 'consumable':
            case 'material':
            case 'hullPlating':
            default:
                if (!playerData.inventory)       playerData.inventory = { items: [] };
                if (!playerData.inventory.items) playerData.inventory.items = [];
                // Stack consumables/materials; unique otherwise
                const existing = playerData.inventory.items.find(i => i.id === item.id && item.stackable);
                if (existing) {
                    existing.quantity = (existing.quantity || 1) + quantity;
                } else {
                    playerData.inventory.items.push({
                        id:       item.id,
                        name:     item.name,
                        type:     item.type,
                        quantity: quantity,
                        acquired: new Date().toISOString()
                    });
                }
                break;
        }

        return {
            totalCost,
            currency,
            newBalance: currency === 'credits' ? playerData.stats.credits : playerData.stats.gems
        };
    }

    // ── Packet builder helpers ─────────────────────────────────────────────

    /** Builds the full shopItemsReceived payload */
    buildShopResponse() {
        return {
            success:   true,
            shopItems: this.getShopItemsByCategory(),
            timestamp: new Date().toISOString()
        };
    }

    /** Builds the itemDetailsReceived payload */
    buildItemDetailResponse(itemId) {
        const item = this.getItem(itemId);
        if (!item) return { success: false, error: `Item '${itemId}' not found` };
        return { success: true, item: this._normaliseForClient(item) };
    }

    // ── Internal normalisation ─────────────────────────────────────────────

    /**
     * Normalise an item object into the flat shape the client expects.
     * Handles both bare-item format (what ContentLoader returns after unwrapping templates)
     * and the raw wrapped format { templates: { <type>: {...} } }.
     */
    _normaliseForClient(item) {
        return {
            id:          item.id,
            name:        item.name || item.id,
            type:        item.type || 'misc',
            rarity:      item.rarity || 'common',
            price:       item.price  || 0,
            currency:    item.currency || 'credits',
            description: item.description || '',
            texture:     item.texture || '',
            texturePath: item.texture || '',
            stats:       item.stats   || {},
            categories:  item.categories || [],
            requirements:item.requirements || {},
            stackable:   item.stackable ?? false,
            maxStack:    item.maxStack   || 1,
            meta:        item.meta       || {}
        };
    }
}

module.exports = ItemSystem;
