// Golf Bag System
// Manages golf club storage in both item and block forms using custom components

import { world, system, ItemStack } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";
import { 
    PUTTERS,
    IRONS,
    FAIRWAYS,
    DRIVERS,
    WEDGES,
    CLUB_VARIANT_NAMES
} from './config.js';
import { debug } from './utils.js';

// Constants
const GOLF_BAG_ITEM_ID = "dss_gep:dss_gep_golf_bag";
const GOLF_BAG_BLOCK_ID = "dss_gep:dss_gep_golf_bag";
const CUSTOM_COMPONENT_ID = "dss:golf_bag"; 

// Club type mappings - now supports all variants
const CLUB_TYPES = {
    putter: { name: "Putter", stateKey: "dss:has_putter", displayName: "§aPutter", variants: PUTTERS },
    wedge: { name: "Wedge", stateKey: "dss:has_wedge", displayName: "§dWedge", variants: WEDGES },
    iron: { name: "Iron", stateKey: "dss:has_iron", displayName: "§bIron", variants: IRONS },
    fairway: { name: "Fairway", stateKey: "dss:has_fairway", displayName: "§eFairway", variants: FAIRWAYS },
    driver: { name: "Driver", stateKey: "dss:has_driver", displayName: "§cDriver", variants: DRIVERS }
};

// New order: Store All, Take All, Putter, Wedge, Iron, Fairway, Driver
const CLUB_ORDER = ['putter', 'wedge', 'iron', 'fairway', 'driver'];

// World Dynamic Components system for persistent golf bag storage
const GOLF_BAG_COMPONENT_PREFIX = "dss:golf_bag_shard_";
const MAX_RECORDS_PER_SHARD = 100; // Keep shards small for performance
const MAX_COMPONENT_SIZE = 3.5 * 1024 * 1024; // 3.5MB safety margin under 4MB limit

// In-memory cache for performance
const golfBagCache = new Map();
let currentShardIndex = 0;

const GolfBagComponent = {
    /**
     * Fired when a player interacts with the market stall block.
     * @param {import("@minecraft/server").BlockComponentPlayerInteractEvent} event 
     */
    onPlayerInteract(event) {
        const { player, block } = event;
        // Defer to the next tick to safely show UI forms.
        system.run(() => {   
            if (event.block?.typeId === GOLF_BAG_BLOCK_ID) {
                handleGolfBagBlockInteract(event);
            }
        });
    }
};

system.beforeEvents.startup.subscribe(event => {
    event.itemComponentRegistry.registerCustomComponent(CUSTOM_COMPONENT_ID, {
        onUse: handleGolfBagItemUse,
        onUseOn: handleGolfBagItemUseOn
    });
    event.blockComponentRegistry.registerCustomComponent(CUSTOM_COMPONENT_ID, GolfBagComponent);
});

// Helper function to get club type from club ID
function getClubType(clubId) {
    for (const [type, info] of Object.entries(CLUB_TYPES)) {
        if (info.variants.includes(clubId)) {
            return type;
        }
    }
    return null;
}

// Helper function to get all club IDs of all variants
function getAllClubIds() {
    const allIds = [];
    for (const type of Object.values(CLUB_TYPES)) {
        allIds.push(...type.variants);
    }
    return allIds;
}

// Helper function to get variant number from club ID
function getVariantNumber(clubId) {
    // Extract number from club ID (e.g., "block_jesu:dss_gep_iron_3" -> 3)
    if (!clubId || typeof clubId !== 'string') {
        return 1;
    }
    
    // Use regex to find the last number in the club ID
    const match = clubId.match(/_(\d+)$/);
    const variantNum = match ? parseInt(match[1]) : 1; // Default to 1 if no number found
    debug('verbose', `Extracting variant number from ${clubId}: match=${match}, result=${variantNum}`);
    return variantNum;
}

// Helper function to get variant name from club ID
function getVariantName(clubId) {
    const variantNumber = getVariantNumber(clubId);
    debug('verbose', `Getting variant name for ${clubId}: number=${variantNumber}, name=${CLUB_VARIANT_NAMES[variantNumber]}`);
    return CLUB_VARIANT_NAMES[variantNumber] || "Oug"; // Default to "Oug" if not found
}

// Helper function to get display name with variant
function getClubDisplayName(clubType, clubId) {
    const clubInfo = CLUB_TYPES[clubType];
    if (!clubId || typeof clubId !== 'string') {
        return clubInfo.displayName;
    }
    
    const variantName = getVariantName(clubId);
    return `${clubInfo.displayName} [${variantName}]`;
}

// Helper function to get block location key
function getBlockLocationKey(block) {
    return `${block.location.x},${block.location.y},${block.location.z}`;
}

// Helper function to get shard component ID for a location
function getShardComponentId(locationKey) {
    // Use hash of location to distribute evenly across shards
    const hash = hashString(locationKey);
    const shardIndex = Math.abs(hash) % 1000; // Support up to 1000 shards
    return `${GOLF_BAG_COMPONENT_PREFIX}${shardIndex}`;
}

// Simple hash function for string
function hashString(str) {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash = hash & hash; // Convert to 32-bit integer
    }
    return hash;
}

// Helper function to load shard data
function loadShardData(shardComponentId) {
    try {
        const component = world.getDynamicProperty(shardComponentId);
        if (component && component !== undefined) {
            const data = JSON.parse(component);
            debug('verbose', `Loaded shard ${shardComponentId} with ${Object.keys(data).length} records`);
            return data;
        } else {
            debug('verbose', `Shard ${shardComponentId} does not exist yet, returning empty data`);
            return {};
        }
    } catch (error) {
        // Check if it's a "property doesn't exist" error vs a real error
        if (error.message && error.message.includes("does not have required privileges")) {
            debug('verbose', `Shard ${shardComponentId} does not exist yet (privileges error), returning empty data`);
            return {};
        } else {
            debug('error', `Failed to load shard ${shardComponentId}: ${error}`);
            return {};
        }
    }
}

// Helper function to save shard data
function saveShardData(shardComponentId, data) {
    try {
        const jsonData = JSON.stringify(data);
        // const sizeInBytes = new TextEncoder().encode(jsonData).length;
        
        // if (sizeInBytes > MAX_COMPONENT_SIZE) {
        //     debug('error', `Shard ${shardComponentId} exceeds size limit: ${sizeInBytes} bytes`);
        //     return false;
        // }
        
        world.setDynamicProperty(shardComponentId, jsonData);
        // debug('verbose', `Saved shard ${shardComponentId} with ${Object.keys(data).length} records (${sizeInBytes} bytes)`);
        return true;
    } catch (error) {
        debug('error', `Failed to save shard ${shardComponentId}: ${error}`);
        return false;
    }
}

// Helper function to store block variant information
function storeBlockVariants(block, clubs) {
    const locationKey = getBlockLocationKey(block);
    const variants = {};
    
    // Extract variant information
    for (const clubType of CLUB_ORDER) {
        if (clubs[clubType] && typeof clubs[clubType] === 'string' && clubs[clubType] !== 'true') {
            variants[clubType] = clubs[clubType];
        }
    }
    
    // Update cache
    if (Object.keys(variants).length > 0) {
        golfBagCache.set(locationKey, variants);
        debug('info', `Cached block variants at ${locationKey}: ${JSON.stringify(variants)}`);
    } else {
        golfBagCache.delete(locationKey);
    }
    
    // Update persistent storage
    const shardComponentId = getShardComponentId(locationKey);
    const shardData = loadShardData(shardComponentId);
    
    if (Object.keys(variants).length > 0) {
        shardData[locationKey] = variants;
    } else {
        delete shardData[locationKey];
    }
    
    saveShardData(shardComponentId, shardData);
    debug('info', `Stored block variants persistently at ${locationKey}`);
}

// Helper function to retrieve block variant information
function retrieveBlockVariants(block) {
    const locationKey = getBlockLocationKey(block);
    
    // Check cache first
    if (golfBagCache.has(locationKey)) {
        const variants = golfBagCache.get(locationKey);
        debug('verbose', `Retrieved block variants from cache at ${locationKey}: ${JSON.stringify(variants)}`);
        return variants;
    }
    
    // Load from persistent storage
    const shardComponentId = getShardComponentId(locationKey);
    const shardData = loadShardData(shardComponentId);
    const variants = shardData[locationKey] || {};
    
    // Update cache
    if (Object.keys(variants).length > 0) {
        golfBagCache.set(locationKey, variants);
    }
    
    debug('info', `Retrieved block variants from storage at ${locationKey}: ${JSON.stringify(variants)}`);
    return variants;
}

// Helper function to clear block variant information
function clearBlockVariants(block) {
    const locationKey = getBlockLocationKey(block);
    
    // Clear from cache
    golfBagCache.delete(locationKey);
    
    // Clear from persistent storage
    const shardComponentId = getShardComponentId(locationKey);
    const shardData = loadShardData(shardComponentId);
    delete shardData[locationKey];
    saveShardData(shardComponentId, shardData);
    
    debug('info', `Cleared block variants at ${locationKey}`);
}

// Utility function to get storage statistics
function getStorageStats() {
    const stats = {
        cacheSize: golfBagCache.size,
        shards: {},
        totalRecords: 0,
        totalSize: 0
    };
    
    // Check all possible shards (this is expensive, use sparingly)
    for (let i = 0; i < 1000; i++) {
        const shardId = `${GOLF_BAG_COMPONENT_PREFIX}${i}`;
        try {
            const component = world.getDynamicProperty(shardId);
            if (component && component !== undefined) {
                const data = JSON.parse(component);
                const recordCount = Object.keys(data).length;
                const size = new TextEncoder().encode(component).length;
                
                stats.shards[i] = { records: recordCount, size: size };
                stats.totalRecords += recordCount;
                stats.totalSize += size;
            }
        } catch (error) {
            // Ignore errors for non-existent shards (privileges error is expected)
            if (!error.message || !error.message.includes("does not have required privileges")) {
                debug('verbose', `Unexpected error checking shard ${shardId}: ${error}`);
            }
        }
    }
    
    return stats;
}

// Utility function to preload frequently accessed shards into cache
function preloadShards() {
    debug('info', 'Preloading golf bag shards into cache...');
    let loadedRecords = 0;
    
    for (let i = 0; i < 100; i++) { // Load first 100 shards
        const shardId = `${GOLF_BAG_COMPONENT_PREFIX}${i}`;
        const shardData = loadShardData(shardId);
        
        for (const [locationKey, variants] of Object.entries(shardData)) {
            golfBagCache.set(locationKey, variants);
            loadedRecords++;
        }
    }
    
    debug('info', `Preloaded ${loadedRecords} golf bag records into cache`);
}

// Utility function to clean up empty shards
function cleanupEmptyShards() {
    debug('info', 'Cleaning up empty golf bag shards...');
    let cleanedShards = 0;
    
    for (let i = 0; i < 1000; i++) {
        const shardId = `${GOLF_BAG_COMPONENT_PREFIX}${i}`;
        
        // Only try to clean shards that actually exist
        try {
            const component = world.getDynamicProperty(shardId);
            if (component && component !== undefined) {
                const shardData = JSON.parse(component);
                
                if (Object.keys(shardData).length === 0) {
                    try {
                        world.setDynamicProperty(shardId, undefined);
                        cleanedShards++;
                        debug('verbose', `Cleaned empty shard ${shardId}`);
                    } catch (error) {
                        debug('error', `Failed to clean shard ${shardId}: ${error}`);
                    }
                }
            }
        } catch (error) {
            // Ignore "does not have required privileges" errors for non-existent shards
            if (!error.message || !error.message.includes("does not have required privileges")) {
                debug('verbose', `Error checking shard ${shardId} for cleanup: ${error}`);
            }
        }
    }
    
    debug('info', `Cleaned up ${cleanedShards} empty shards`);
}

/**
 * Parse clubs from item lore
 * @param {ItemStack} itemStack - The golf bag item
 * @returns {Object} Object with club type IDs as keys and boolean values
 */
function parseClubsFromLore(itemStack) {
    debug('verbose', 'Parsing clubs from item lore');
    const clubs = {};
    CLUB_ORDER.forEach(clubType => clubs[clubType] = false);
    
    if (!itemStack?.getLore) {
        debug('warn', 'ItemStack has no lore, returning empty clubs');
        return clubs;
    }
    
    const lore = itemStack.getLore();
    debug('verbose', `Found ${lore.length} lore lines`);
    
    // Debug: Log each lore line to see the actual content
    for (let i = 0; i < lore.length; i++) {
        debug('verbose', `Lore line ${i}: "${lore[i]}"`);
    }
    
    for (const line of lore) {
        for (const clubType of CLUB_ORDER) {
            const clubInfo = CLUB_TYPES[clubType];
            const clubName = clubInfo.name;
            const displayName = clubInfo.displayName;
            
            // Try multiple patterns to match stored clubs, including variant names
            const patterns = [
                `§a${clubName}`,
                `§a${displayName}`,
                clubName,
                displayName
            ];
            
            // Check for variant patterns like "§aPutter [Temon]"
            for (const variantName of Object.values(CLUB_VARIANT_NAMES)) {
                patterns.push(`§a${displayName} [${variantName}]`);
                patterns.push(`${displayName} [${variantName}]`);
            }
            
            for (const pattern of patterns) {
                if (line.includes(pattern) && line.includes('§a')) {
                    // If it's a variant pattern, try to extract the club ID
                    const cleanDisplayName = displayName.replace(/§./g, ''); // Remove color codes
                    // Pattern needs to account for color codes in the actual line
                    const variantMatch = line.match(new RegExp(`§a§.${cleanDisplayName} \\[([^\\]]+)\\]`));
                    debug('verbose', `Checking line "${line}" for variant pattern: §a§.${cleanDisplayName} \\[([^\\]]+)\\]`);
                    if (variantMatch) {
                        const variantName = variantMatch[1];
                        debug('info', `Found variant pattern: ${variantName}`);
                        // Find the club ID that matches this variant name
                        for (const clubId of clubInfo.variants) {
                            if (getVariantName(clubId) === variantName) {
                                clubs[clubType] = clubId;
                                debug('info', `Found stored club variant: ${clubName} [${variantName}] -> ${clubId}`);
                                break;
                            }
                        }
                        if (!clubs[clubType]) {
                            debug('warn', `Could not find club ID for variant name: ${variantName}`);
                        }
                    } else {
                        clubs[clubType] = true; // Backward compatibility
                        debug('info', `Found stored club: ${clubName} (matched pattern: "${pattern}")`);
                    }
                    break;
                }
            }
        }
    }
    
    const storedCount = Object.values(clubs).filter(Boolean).length;
    debug('info', `Parsed ${storedCount} stored clubs from lore`);
    return clubs;
}

/**
 * Update item lore based on stored clubs
 * @param {ItemStack} itemStack - The golf bag item
 * @param {Object} clubs - Object with club type IDs as keys and boolean values
 */
function updateItemLore(itemStack, clubs) {
    debug('verbose', 'Updating item lore');
    const lore = ["§7Golf Bag Contents:", ""];
    let hasClubs = false;
    
    for (const clubType of CLUB_ORDER) {
        const clubInfo = CLUB_TYPES[clubType];
        if (clubs[clubType]) {
            // Show the specific variant name if stored as club ID
            const storedValue = clubs[clubType];
            debug('info', `Processing club ${clubType}: stored value = ${storedValue}, type = ${typeof storedValue}`);
            const displayText = typeof storedValue === 'string' && storedValue !== 'true' ?
                getClubDisplayName(clubType, storedValue) : clubInfo.displayName;
            lore.push(`§a${displayText}`);
            hasClubs = true;
            debug('info', `Added stored club to lore: ${clubInfo.name} -> ${displayText}`);
        }
    }
    
    if (!hasClubs) {
        lore.push("", "§7Empty - Use/Interact to manage");
        debug('info', 'Updated lore for empty golf bag');
    } else {
        lore.push("", "§7Use/Interact to manage clubs");
        debug('info', `Updated lore with ${Object.values(clubs).filter(club => !!club).length} stored clubs`);
    }
    itemStack.setLore(lore);
}

/**
 * Parse clubs from block states
 * @param {Block} block - The golf bag block
 * @returns {Object} Object with club type IDs as keys and boolean values
 */
function parseClubsFromBlockStates(block) {
    debug('verbose', 'Parsing clubs from block states');
    const clubs = {};
    const variants = retrieveBlockVariants(block);
    
    for (const clubType of CLUB_ORDER) {
        const clubInfo = CLUB_TYPES[clubType];
        const stateKey = clubInfo.stateKey;
        const hasClub = block.permutation.getState(stateKey) === "true";
        
        if (hasClub) {
            // Check if we have variant information for this club type
            if (variants[clubType]) {
                clubs[clubType] = variants[clubType];
                debug('info', `Found stored club variant in block: ${clubInfo.name} -> ${variants[clubType]}`);
            } else {
                clubs[clubType] = true;
                debug('info', `Found stored club in block (no variant): ${clubInfo.name}`);
            }
        } else {
            clubs[clubType] = false;
        }
    }
    
    const storedCount = Object.values(clubs).filter(Boolean).length;
    debug('info', `Parsed ${storedCount} stored clubs from block states`);
    return clubs;
}

/**
 * Update block states based on stored clubs
 * @param {Block} block - The golf bag block
 * @param {Object} clubs - Object with club type IDs as keys and boolean values
 */
function updateBlockStates(block, clubs) {
    debug('verbose', 'Updating block states');
    let permutation = block.permutation;
    
    // Store variant information in memory
    storeBlockVariants(block, clubs);
    
    for (const clubType of CLUB_ORDER) {
        const clubInfo = CLUB_TYPES[clubType];
        const stateKey = clubInfo.stateKey;
        const newState = clubs[clubType] ? "true" : "false";
        permutation = permutation.withState(stateKey, newState);
        if (clubs[clubType]) {
            debug('verbose', `Set block state ${stateKey} = true`);
        }
    }
    
    const storedCount = Object.values(clubs).filter(club => !!club).length;
    debug('info', `Updated block states with ${storedCount} stored clubs`);
    block.setPermutation(permutation);
}

/**
 * Get player's inventory clubs by type
 * @param {Player} player - The player
 * @returns {Object} Object with available club counts by type and specific club IDs
 */
function getPlayerClubs(player) {
    const inventory = player.getComponent("minecraft:inventory").container;
    const availableClubs = {};
    const availableClubIds = {}; // Track specific club IDs for variants
    
    // Initialize counters
    for (const clubType of CLUB_ORDER) {
        availableClubs[clubType] = 0;
        availableClubIds[clubType] = [];
    }
    
    // Scan inventory for all club variants
    for (let i = 0; i < inventory.size; i++) {
        const item = inventory.getItem(i);
        if (item) {
            const clubType = getClubType(item.typeId);
            if (clubType) {
                availableClubs[clubType] += item.amount;
                // Store the specific club ID and slot for later use
                for (let j = 0; j < item.amount; j++) {
                    availableClubIds[clubType].push({ clubId: item.typeId, slot: i, item: item });
                }
            }
        }
    }
    
    return { availableClubs, availableClubIds };
}

/**
 * Add club to player inventory
 * @param {Player} player - The player
 * @param {string} clubId - Club type ID
 * @returns {boolean} True if successfully added
 */
function addClubToInventory(player, clubId) {
    const inventory = player.getComponent("minecraft:inventory").container;
    const clubItem = new ItemStack(clubId, 1);
    
    try {
        inventory.addItem(clubItem);
        return true;
    } catch (error) {
        // Inventory full, try to drop at player location
        player.dimension.spawnItem(clubItem, player.location);
        player.sendMessage("§eInventory full! Club dropped at your feet.");
        return true;
    }
}

/**
 * Remove club from player inventory by type (any variant)
 * @param {Player} player - The player
 * @param {string} clubType - Club type (putter, iron, etc.)
 * @returns {Object} {success: boolean, clubId: string} - Returns the specific club ID that was removed
 */
function removeClubFromInventory(player, clubType) {
    const inventory = player.getComponent("minecraft:inventory").container;
    debug('info', `Removing club of type ${clubType} from inventory`);
    
    // Find any club of the specified type
    for (let i = 0; i < inventory.size; i++) {
        const item = inventory.getItem(i);
        if (item) {
            const itemClubType = getClubType(item.typeId);
            debug('verbose', `Checking slot ${i}: item=${item.typeId}, detected type=${itemClubType}`);
            if (itemClubType === clubType) {
                const removedClubId = item.typeId;
                debug('info', `Found matching club: ${removedClubId}, removing from inventory`);
                if (item.amount > 1) {
                    item.amount--;
                    inventory.setItem(i, item);
                } else {
                    inventory.setItem(i, undefined);
                }
                return { success: true, clubId: removedClubId };
            }
        }
    }
    
    debug('warn', `No club of type ${clubType} found in inventory`);
    return { success: false, clubId: null };
}

/**
 * Show golf bag management UI with bulk operations and new arrangement
 * @param {Player} player - The player
 * @param {Object} storedClubs - Currently stored clubs by type
 * @param {Function} onUpdate - Callback function when clubs are updated
 * @param {string} containerType - "item" or "block"
 */
function showGolfBagUI(player, storedClubs, onUpdate, containerType = "item") {
    const { availableClubs, availableClubIds } = getPlayerClubs(player);
    const form = new ActionFormData()
        .title(`§6Golf Bag Management`)
        .body("§7Choose an action:");
    
    const buttonActions = [];
    
    // 1. Store All button (if player has any clubs and bag has space)
    const hasAvailableClubs = Object.values(availableClubs).some(count => count > 0);
    const hasStorageSpace = CLUB_ORDER.some(type => !storedClubs[type] && availableClubs[type] > 0);
    if (hasAvailableClubs && hasStorageSpace) {
        form.button("§aStore All Available", "textures/ui/plus");
        buttonActions.push({ action: 'store_all' });
    }
    
    // 2. Take All button (if bag has any clubs)
    const hasStoredClubs = Object.values(storedClubs).some(Boolean);
    if (hasStoredClubs) {
        form.button("§bTake All Stored", "textures/ui/minus");
        buttonActions.push({ action: 'take_all' });
    }
    
    // 3-7. Individual club management in order: Putter, Wedge, Iron, Fairway, Driver
    for (const clubType of CLUB_ORDER) {
        const clubInfo = CLUB_TYPES[clubType];
        const available = availableClubs[clubType];
        const stored = storedClubs[clubType];
        const item_icon_stored = `textures/dss/gep/items/${getVariantName(stored).toLowerCase()}/dss_gep_` + clubInfo.name.toLowerCase() + "_icon";
        const item_icon_available = available > 0 ? 
            `textures/dss/gep/items/${getVariantName(availableClubIds[clubType][0].clubId).toLowerCase()}/dss_gep_` + clubInfo.name.toLowerCase() + "_icon" :
            null;
        
        if (!stored && available > 0) {
            // Store option
            form.button(`§8Store ${clubInfo.displayName} (§f${available}§8)`, item_icon_available + ".png");
            buttonActions.push({ action: 'store', clubType: clubType });
        } else if (stored) {
            // Take option - show variant name if available
            const displayText = typeof stored === 'string' && stored !== 'true' ?
                getClubDisplayName(clubType, stored) : clubInfo.displayName;
            form.button(`§8Take ${displayText}`, item_icon_stored + ".png");
            buttonActions.push({ action: 'take', clubType: clubType });
        }
    }
    
    // Status display
    let statusText = "§7Stored Clubs (1 per type max):\n";
    let displayedClubs = false;
    for (const clubType of CLUB_ORDER) {
        const clubInfo = CLUB_TYPES[clubType];
        if (storedClubs[clubType]) {
            const stored = storedClubs[clubType];
            const displayText = typeof stored === 'string' && stored !== 'true' ?
                `${clubInfo.name} [${getVariantName(stored)}]` : clubInfo.name;
            statusText += `§a✓ ${displayText}\n`;
            displayedClubs = true;
        }
    }
    if (!displayedClubs) {
        statusText += "§8None";
    }
    
    form.button("§cClose", "textures/ui/cancel");
    buttonActions.push({ action: 'close' });
    
    form.show(player).then(response => {
        if (response.canceled || response.selection === undefined) return;
        
        const selectedAction = buttonActions[response.selection];
        if (!selectedAction) return;
        
        switch (selectedAction.action) {
            case 'store_all':
                handleStoreAll(player, storedClubs, availableClubIds, onUpdate);
                break;
                
            case 'take_all':
                handleTakeAll(player, storedClubs, onUpdate);
                break;
                
            case 'store':
                handleStoreClub(player, selectedAction.clubType, storedClubs, onUpdate);
                break;
                
            case 'take':
                handleTakeClub(player, selectedAction.clubType, storedClubs, onUpdate);
                break;
                
            case 'close':
            default:
                // Do nothing, just close
                break;
        }
    });
}

/**
 * Handle storing all available clubs
 * @param {Player} player - The player
 * @param {Object} storedClubs - Currently stored clubs
 * @param {Object} availableClubIds - Available club IDs by type
 * @param {Function} onUpdate - Update callback
 */
function handleStoreAll(player, storedClubs, availableClubIds, onUpdate) {
    let storedCount = 0;
    const storedTypes = [];
    
    for (const clubType of CLUB_ORDER) {
        // Only store if not already stored and player has this type
        if (!storedClubs[clubType] && availableClubIds[clubType].length > 0) {
            const result = removeClubFromInventory(player, clubType);
            if (result.success) {
                storedClubs[clubType] = result.clubId; // Store the specific club ID
                const variantName = getVariantName(result.clubId);
                storedTypes.push(`${CLUB_TYPES[clubType].name} [${variantName}]`);
                storedCount++;
            }
        }
    }
    
    if (storedCount > 0) {
        onUpdate(storedClubs);
        player.onScreenDisplay.setActionBar(`§aStored ${storedCount} clubs: ${storedTypes.join(', ')}`);
    } else {
        player.onScreenDisplay.setActionBar("§cNo clubs available to store!");
    }
}

/**
 * Handle taking all stored clubs
 * @param {Player} player - The player
 * @param {Object} storedClubs - Currently stored clubs
 * @param {Function} onUpdate - Update callback
 */
function handleTakeAll(player, storedClubs, onUpdate) {
    let takenCount = 0;
    const takenTypes = [];
    
    for (const clubType of CLUB_ORDER) {
        if (storedClubs[clubType]) {
            // Use the stored club ID or default to first variant
            const clubId = typeof storedClubs[clubType] === 'string' ? 
                storedClubs[clubType] : CLUB_TYPES[clubType].variants[0];
            
            if (addClubToInventory(player, clubId)) {
                const variantName = getVariantName(clubId);
                storedClubs[clubType] = false;
                takenTypes.push(`${CLUB_TYPES[clubType].name} [${variantName}]`);
                takenCount++;
            }
        }
    }
    
    if (takenCount > 0) {
        onUpdate(storedClubs);
        player.onScreenDisplay.setActionBar(`§aTook ${takenCount} clubs: ${takenTypes.join(', ')}`);
    } else {
        player.onScreenDisplay.setActionBar("§cNo clubs stored to take!");
    }
}

/**
 * Handle storing a specific club type
 * @param {Player} player - The player
 * @param {string} clubType - Club type to store
 * @param {Object} storedClubs - Currently stored clubs
 * @param {Function} onUpdate - Update callback
 */
function handleStoreClub(player, clubType, storedClubs, onUpdate) {
    if (storedClubs[clubType]) {
        player.onScreenDisplay.setActionBar(`§c${CLUB_TYPES[clubType].name} already stored!`);
        return;
    }
    
    const result = removeClubFromInventory(player, clubType);
    debug('info', `Store club result for ${clubType}: success=${result.success}, clubId=${result.clubId}`);
    if (result.success) {
        storedClubs[clubType] = result.clubId; // Store the specific club ID
        debug('info', `Stored club ${clubType} with ID: ${result.clubId}`);
        onUpdate(storedClubs);
        const variantName = getVariantName(result.clubId);
        debug('info', `Variant name for stored club: ${variantName}`);
        player.onScreenDisplay.setActionBar(`§a${CLUB_TYPES[clubType].name} [${variantName}] stored in golf bag!`);
    } else {
        player.onScreenDisplay.setActionBar("§cFailed to store club!");
    }
}

/**
 * Handle taking a specific club type
 * @param {Player} player - The player
 * @param {string} clubType - Club type to take
 * @param {Object} storedClubs - Currently stored clubs
 * @param {Function} onUpdate - Update callback
 */
function handleTakeClub(player, clubType, storedClubs, onUpdate) {
    if (!storedClubs[clubType]) {
        player.onScreenDisplay.setActionBar(`§cNo ${CLUB_TYPES[clubType].name} stored!`);
        return;
    }
    
    // Use the stored club ID or default to first variant
    const storedValue = storedClubs[clubType];
    debug('info', `Taking club ${clubType}: stored value = ${storedValue}, type = ${typeof storedValue}`);
    
    const clubId = typeof storedValue === 'string' && storedValue !== 'true' ? 
        storedValue : CLUB_TYPES[clubType].variants[0];
    
    debug('info', `Resolved club ID for ${clubType}: ${clubId}`);
    
    if (addClubToInventory(player, clubId)) {
        storedClubs[clubType] = false;
        onUpdate(storedClubs);
        const variantName = getVariantName(clubId);
        debug('info', `Successfully took club ${clubType} [${variantName}] with ID: ${clubId}`);
        player.onScreenDisplay.setActionBar(`§a${CLUB_TYPES[clubType].name} [${variantName}] taken from golf bag!`);
    } else {
        player.onScreenDisplay.setActionBar("§cFailed to take club!");
    }
}

/**
 * Handle golf bag item use
 * @param {Object} event - Item use event
 */
function handleGolfBagItemUse(event) {
    const { source: player, itemStack } = event;
    if (!player || !itemStack) {
        debug('error', 'Golf bag item use event missing player or itemStack');
        return;
    }
    
    debug('info', `Player ${player.name} used golf bag item`);
    const storedClubs = parseClubsFromLore(itemStack);
    
    showGolfBagUI(player, storedClubs, (updatedClubs) => {
        debug('info', `Updating golf bag item for player ${player.name}`);
        updateItemLore(itemStack, updatedClubs);
        
        // Update the item in player's hand
        const inventory = player.getComponent("minecraft:inventory").container;
        const selectedSlot = player.selectedSlotIndex;
        inventory.setItem(selectedSlot, itemStack);
        debug('verbose', 'Updated golf bag item in player inventory');
    }, "item");
}

/**
 * Handle golf bag item use on block (placement)
 * @param {Object} event - Item use on block event
 */
function handleGolfBagItemUseOn(event) {
    const { source: player, itemStack, block, blockFace } = event;
    if (!player || !itemStack) {
        debug('error', 'Golf bag item placement event missing player or itemStack');
        return;
    }
    
    debug('info', `Player ${player.name} placing golf bag block`);
    const storedClubs = parseClubsFromLore(itemStack);
    
    // Calculate the target placement location based on block face
    const targetLocation = {
        x: block.location.x,
        y: block.location.y,
        z: block.location.z
    };
    
    // Adjust location based on block face
    switch (blockFace) {
        case 'Up': targetLocation.y += 1; break;
        case 'Down': targetLocation.y -= 1; break;
        case 'North': targetLocation.z -= 1; break;
        case 'South': targetLocation.z += 1; break;
        case 'East': targetLocation.x += 1; break;
        case 'West': targetLocation.x -= 1; break;
    }
    
    debug('verbose', `Target placement location: ${targetLocation.x}, ${targetLocation.y}, ${targetLocation.z}`);
    
    // Retry mechanism for finding the placed block
    let retryCount = 0;
    const maxRetries = 5;
    
    const syncBlockStates = () => {
        const placedBlock = block.dimension.getBlock(targetLocation);
        
        if (placedBlock && placedBlock.typeId === GOLF_BAG_BLOCK_ID) {
            debug('info', `Found placed golf bag block after ${retryCount} retries`);
            updateBlockStates(placedBlock, storedClubs);
            return;
        }
        
        retryCount++;
        if (retryCount < maxRetries) {
            debug('verbose', `Block not found, retry ${retryCount}/${maxRetries}`);
            system.run(syncBlockStates);
        } else {
            debug('warn', `Failed to find placed golf bag block after ${maxRetries} retries`);
            // Try alternative locations around the target
            const offsets = [
                {x: 0, y: 0, z: 0}, {x: 1, y: 0, z: 0}, {x: -1, y: 0, z: 0},
                {x: 0, y: 1, z: 0}, {x: 0, y: -1, z: 0}, {x: 0, y: 0, z: 1}, {x: 0, y: 0, z: -1}
            ];
            
            for (const offset of offsets) {
                const checkLocation = {
                    x: targetLocation.x + offset.x,
                    y: targetLocation.y + offset.y,
                    z: targetLocation.z + offset.z
                };
                
                const checkBlock = block.dimension.getBlock(checkLocation);
                if (checkBlock && checkBlock.typeId === GOLF_BAG_BLOCK_ID) {
                    debug('info', `Found golf bag block at offset location: ${offset.x}, ${offset.y}, ${offset.z}`);
                    updateBlockStates(checkBlock, storedClubs);
                    return;
                }
            }
            
            debug('error', 'Could not find placed golf bag block anywhere nearby');
        }
    };
    
    // Start the sync process with a small delay
    system.run(syncBlockStates);
}

/**
 * Handle golf bag block interaction
 * @param {Object} event - Block interaction event
 */
function handleGolfBagBlockInteract(event) {
    const { player, block } = event;
    if (!player || !block) {
        debug('error', 'Golf bag block interact event missing player or block');
        return;
    }
    
    debug('info', `Player ${player.name} interacting with golf bag block`);
    const storedClubs = parseClubsFromBlockStates(block);
    
    showGolfBagUI(player, storedClubs, (updatedClubs) => {
        debug('info', `Updating golf bag block states for player ${player.name}`);
        updateBlockStates(block, updatedClubs);
    }, "block");
}

/**
 * Handle golf bag block breaking using world event
 * @param {Object} event - Block break event
 */
function handleGolfBagBlockBreak(event) {
    const { block, player } = event;
    if (!block || !player) {
        debug('error', 'Golf bag block break event missing block or player');
        return;
    }
    
    // Only handle golf bag blocks
    if (block.typeId !== GOLF_BAG_BLOCK_ID) {
        return;
    }
    
    debug('info', `Player ${player.name} breaking golf bag block`);
    
    // Get stored clubs from the block before it's destroyed
    const storedClubs = parseClubsFromBlockStates(block);
    
    // Create the golf bag item with proper lore
    const golfBagItem = new ItemStack(GOLF_BAG_ITEM_ID, 1);
    system.run(() => {
        updateItemLore(golfBagItem, storedClubs);
        debug('info', 'Created golf bag item with synced lore from block states');
        
        // Clear variant memory for this block
        clearBlockVariants(block);
        
        // Drop the item at block location
        block.dimension.spawnItem(golfBagItem, {
            x: block.location.x + 0.5,
            y: block.location.y + 0.5,
            z: block.location.z + 0.5
        });
        debug('verbose', 'Dropped golf bag item at block location');
    });
}
/**
 * Initialize golf bag system
 */
export function initializeGolfBagSystem() {
    debug('info', 'Initializing Golf Bag System with persistent storage...');
    
    // Initialize persistent storage system
    try {
        preloadShards();
        debug('info', 'Golf bag persistent storage initialized');
    } catch (error) {
        debug('error', `Failed to initialize persistent storage: ${error}`);
    }
    
    // Register item use event for golf bag items
    // world.afterEvents.itemUse.subscribe((event) => {
    //     if (event.itemStack?.typeId === GOLF_BAG_ITEM_ID) {
    //         handleGolfBagItemUse(event);
    //     }
    // });
    // debug('verbose', 'Registered golf bag item use event handler');
    
    // // Register item use on block event for golf bag placement
    // world.afterEvents.itemUse.subscribe((event) => {
    //     if (event.itemStack?.typeId === GOLF_BAG_ITEM_ID) {
    //         handleGolfBagItemUseOn(event);
    //     }
    // });
    // debug('verbose', 'Registered golf bag item placement event handler');
    
    // Register block interaction event for golf bag blocks
    // world.afterEvents.playerInteractWithBlock.subscribe((event) => {
    //     if (event.block?.typeId === GOLF_BAG_BLOCK_ID) {
    //         handleGolfBagBlockInteract(event);
    //     }
    // });
    // debug('verbose', 'Registered golf bag block interaction event handler');
    
    // Register world event for block breaking
    world.beforeEvents.playerBreakBlock.subscribe((event) => {
       handleGolfBagBlockBreak(event);
    });
    debug('verbose', 'Registered golf bag block break event handler');
    
    // Schedule periodic cleanup (every 5 minutes)
    system.runInterval(() => {
        cleanupEmptyShards();
    }, 6000); // 6000 ticks = 5 minutes
    
    debug('info', 'Golf Bag System initialized successfully with persistent storage!');
}

// Test variant detection function
function testVariantDetection() {
    debug('info', '=== Testing Variant Detection ===');
    const testClubs = [
        "block_jesu:dss_gep_golf_putter",
        "block_jesu:dss_gep_golf_putter_2", 
        "block_jesu:dss_gep_iron_3",
        "block_jesu:dss_gep_driver_4",
        "block_jesu:dss_gep_wedge_5"
    ];
    
    for (const clubId of testClubs) {
        const variantNum = getVariantNumber(clubId);
        const variantName = getVariantName(clubId);
        const clubType = getClubType(clubId);
        debug('info', `Club: ${clubId} -> Type: ${clubType}, Variant: ${variantNum} (${variantName})`);
    }
    debug('info', '=== End Variant Detection Test ===');
}

// Auto-initialize when imported
initializeGolfBagSystem();

// Run test on startup
system.run(() => {
    testVariantDetection();
    
    // Log storage stats after initialization
    system.runTimeout(() => {
        const stats = getStorageStats();
        debug('info', `Golf Bag Storage Stats: ${stats.totalRecords} records across ${Object.keys(stats.shards).length} shards, ${Math.round(stats.totalSize / 1024)}KB total`);
    }, 100); // Delay to allow initialization to complete
});