/**
 * UNLOCK SYSTEM
 * =============
 * 
 * Handles all unlock logic for doors and items.
 * Supports multiple lock types: key, pin, password, biometric, bluetooth.
 * This system coordinates between various subsystems to perform unlocking.
 */

import { DOOR_ALIGN_OVERLAP } from '../utils/constants.js';
import { rooms } from '../core/rooms.js';
import { unlockDoor } from './doors.js';
import { startLockpickingMinigame, startKeySelectionMinigame, startPinMinigame, startPasswordMinigame } from './minigame-starters.js';
import { playUISound } from './ui-sounds.js?v=1';

// Helper function to check if two rectangles overlap
function boundsOverlap(rect1, rect2) {
    return rect1.x < rect2.x + rect2.width &&
           rect1.x + rect1.width > rect2.x &&
           rect1.y < rect2.y + rect2.height &&
           rect1.y + rect1.height > rect2.y;
}

export function handleUnlock(lockable, type) {
    console.log('UNLOCK ATTEMPT');
    playUISound('lock');
    
    // Check if locks are disabled for testing
    if (window.DISABLE_LOCKS) {
        console.log('LOCKS DISABLED FOR TESTING - Unlocking directly');
        unlockTarget(lockable, type, lockable.layer);
        return;
    }
    
    // Get lock requirements based on type
    const lockRequirements = type === 'door' 
        ? getLockRequirementsForDoor(lockable)
        : getLockRequirementsForItem(lockable);
    
    if (!lockRequirements) {
        console.log('NO LOCK REQUIREMENTS FOUND');
        return;
    }
    
    // Check if object is locked based on lock requirements
    const isLocked = lockRequirements.requires;
    
    if (!isLocked) {
        console.log('OBJECT NOT LOCKED');
        return;
    }
    
    // Emit unlock attempt event
    if (window.eventDispatcher && type === 'door') {
        const doorProps = lockable.doorProperties || {};
        window.eventDispatcher.emit('door_unlock_attempt', {
            roomId: doorProps.roomId,
            connectedRoom: doorProps.connectedRoom,
            direction: doorProps.direction,
            lockType: lockRequirements.lockType
        });
    }
    
    switch(lockRequirements.lockType) {
        case 'key':
            const requiredKey = lockRequirements.requires;
            console.log('KEY REQUIRED', requiredKey);
            
            // Get all keys from player's inventory (including key ring)
            let playerKeys = [];
            
            // Check for individual keys
            const individualKeys = window.inventory.items.filter(item => 
                item && item.scenarioData && 
                item.scenarioData.type === 'key'
            );
            playerKeys = playerKeys.concat(individualKeys);
            
            // Check for key ring
            const keyRingItem = window.inventory.items.find(item => 
                item && item.scenarioData && 
                item.scenarioData.type === 'key_ring'
            );
            
            if (keyRingItem && keyRingItem.scenarioData.allKeys) {
                // Convert key ring keys to the format expected by the minigame
                const keyRingKeys = keyRingItem.scenarioData.allKeys.map(keyData => {
                    // Create a mock inventory item for each key in the ring
                    return {
                        scenarioData: keyData,
                        name: 'key',
                        objectId: `key_ring_${keyData.key_id || keyData.name}`
                    };
                });
                playerKeys = playerKeys.concat(keyRingKeys);
            }
            
            // Check for lockpick kit
            const hasLockpick = window.inventory.items.some(item => 
                item && item.scenarioData && 
                item.scenarioData.type === 'lockpick'
            );
            
            if (playerKeys.length > 0) {
                // Keys take priority - go straight to key selection
                console.log('KEYS AVAILABLE - STARTING KEY SELECTION');
                startKeySelectionMinigame(lockable, type, playerKeys, requiredKey, unlockTarget);
            } else if (hasLockpick) {
                // Only lockpick available - launch lockpicking minigame directly
                console.log('LOCKPICK AVAILABLE - STARTING LOCKPICKING MINIGAME');
                
                // CHECK: Should any NPC interrupt with person-chat instead?
                const roomId = lockable.doorProperties?.roomId || window.currentRoomId;
                if (window.npcManager && roomId) {
                    // Get player position for LOS check
                    const playerPos = window.player?.sprite?.getCenter ? 
                      window.player.sprite.getCenter() : 
                      { x: window.player?.x || 0, y: window.player?.y || 0 };
                    
                    const interruptingNPC = window.npcManager.shouldInterruptLockpickingWithPersonChat(roomId, playerPos);
                    if (interruptingNPC) {
                        console.log(`🚫 LOCKPICKING INTERRUPTED: Triggering person-chat with NPC "${interruptingNPC.id}"`);
                        
                        // Trigger the lockpick event which will start person-chat
                        if (window.npcManager.eventDispatcher) {
                            window.npcManager.eventDispatcher.emit('lockpick_used_in_view', {
                                npcId: interruptingNPC.id,
                                roomId: roomId,
                                lockable: lockable,
                                timestamp: Date.now()
                            });
                        }
                        return;  // Don't start lockpicking minigame
                    }
                }
                
                let difficulty = lockable.doorProperties?.difficulty || lockable.scenarioData?.difficulty || lockable.properties?.difficulty || lockRequirements.difficulty || 'medium';
                // Check for both keyPins (camelCase) and key_pins (snake_case)
                let keyPins = lockable.doorProperties?.keyPins || lockable.doorProperties?.key_pins ||
                              lockable.scenarioData?.keyPins || lockable.scenarioData?.key_pins ||
                              lockable.properties?.keyPins || lockable.properties?.key_pins ||
                              lockRequirements.keyPins || lockRequirements.key_pins;
                
                console.log('🔓 Door/Item lock details:', {
                    hasDoorProperties: !!lockable.doorProperties,
                    doorKeyPins: lockable.doorProperties?.keyPins,
                    hasScenarioData: !!lockable.scenarioData,
                    scenarioKeyPins: lockable.scenarioData?.keyPins,
                    hasProperties: !!lockable.properties,
                    propertiesKeyPins: lockable.properties?.keyPins,
                    lockRequirementsKeyPins: lockRequirements.keyPins,
                    finalKeyPins: keyPins,
                    finalDifficulty: difficulty
                });
                
                startLockpickingMinigame(lockable, window.game, difficulty, (success) => {
                    if (success) {
                        setTimeout(() => {
                            unlockTarget(lockable, type, lockable.layer);
                            window.gameAlert(`Successfully picked the lock!`, 'success', 'Lock Picked', 4000);
                        }, 100);
                    } else {
                        console.log('LOCKPICK FAILED');
                        window.gameAlert('Failed to pick the lock. Try again.', 'error', 'Pick Failed', 3000);
                    }
                }, keyPins);  // Pass keyPins to minigame starter
            } else {
                console.log('NO KEYS OR LOCKPICK AVAILABLE');
                window.gameAlert(`Requires key`, 'error', 'Locked', 4000);
            }
            break;

        case 'pin':
            console.log('PIN CODE REQUESTED');
            startPinMinigame(lockable, type, lockRequirements.requires, (success) => {
                if (success) {
                    unlockTarget(lockable, type, lockable.layer);
                }
            });
            break;
            
        case 'password':
            console.log('PASSWORD REQUESTED');
            
            // Get password options from the lockable object
            const passwordOptions = {
                passwordHint: lockable.passwordHint || lockable.scenarioData?.passwordHint || '',
                showHint: lockable.showHint || lockable.scenarioData?.showHint || false,
                showKeyboard: lockable.showKeyboard || lockable.scenarioData?.showKeyboard || false,
                maxAttempts: lockable.maxAttempts || lockable.scenarioData?.maxAttempts || 3,
                postitNote: lockable.postitNote || lockable.scenarioData?.postitNote || '',
                showPostit: lockable.showPostit || lockable.scenarioData?.showPostit || false
            };
            
            startPasswordMinigame(lockable, type, lockRequirements.requires, (success) => {
                if (success) {
                    unlockTarget(lockable, type, lockable.layer);
                }
            }, passwordOptions);
            break;
            
        case 'biometric':
            const requiredFingerprint = lockRequirements.requires;
            console.log('BIOMETRIC LOCK REQUIRES', requiredFingerprint);
            
            // Check if we have fingerprints in the biometricSamples collection
            const biometricSamples = window.gameState?.biometricSamples || [];
            
            console.log('BIOMETRIC SAMPLES', JSON.stringify(biometricSamples));
            
            // Get the required match threshold from the object or use default
            const requiredThreshold = lockable.biometricMatchThreshold || 0.4;
            console.log('BIOMETRIC THRESHOLD', requiredThreshold);
            
            // Find the fingerprint sample for the required person
            const fingerprintSample = biometricSamples.find(sample => 
                sample.owner === requiredFingerprint
            );
            
            const hasFingerprint = fingerprintSample !== undefined;
            console.log('FINGERPRINT CHECK', `Looking for '${requiredFingerprint}'. Found: ${hasFingerprint}`);
            
            if (hasFingerprint) {
                // Get the quality from the sample
                let fingerprintQuality = fingerprintSample.quality;
                
                // Normalize quality to 0-1 range if it's in percentage format
                if (fingerprintQuality > 1) {
                    fingerprintQuality = fingerprintQuality / 100;
                }
                
                console.log('BIOMETRIC CHECK', 
                    `Required: ${requiredFingerprint}, Quality: ${fingerprintQuality} (${Math.round(fingerprintQuality * 100)}%), Threshold: ${requiredThreshold} (${Math.round(requiredThreshold * 100)}%)`);
                
                // Check if the fingerprint quality meets the threshold
                if (fingerprintQuality >= requiredThreshold) {
                    console.log('BIOMETRIC UNLOCK SUCCESS');
                    unlockTarget(lockable, type, lockable.layer);
                    window.gameAlert(`You successfully unlocked the ${type} with ${requiredFingerprint}'s fingerprint.`, 
                        'success', 'Biometric Unlock Successful', 5000);
                } else {
                    console.log('BIOMETRIC QUALITY TOO LOW', 
                        `Quality: ${fingerprintQuality} (${Math.round(fingerprintQuality * 100)}%) < Threshold: ${requiredThreshold} (${Math.round(requiredThreshold * 100)}%)`);
                    window.gameAlert(`The fingerprint quality (${Math.round(fingerprintQuality * 100)}%) is too low for this lock. 
                            It requires at least ${Math.round(requiredThreshold * 100)}% quality.`,
                        'error', 'Biometric Authentication Failed', 5000);
                }
            } else {
                console.log('MISSING REQUIRED FINGERPRINT', 
                    `Required: '${requiredFingerprint}', Available: ${biometricSamples.map(s => s.owner).join(", ") || "none"}`);
                window.gameAlert(`This ${type} requires ${requiredFingerprint}'s fingerprint, which you haven't collected yet.`,
                    'error', 'Biometric Authentication Failed', 5000);
            }
            break;
            
        case 'bluetooth':
            console.log('BLUETOOTH UNLOCK ATTEMPT');
            const requiredDevice = lockRequirements.requires; // MAC address or device name
            console.log('BLUETOOTH DEVICE REQUIRED', requiredDevice);
            
            // Check if we have a bluetooth scanner in inventory
            const hasScanner = window.inventory.items.some(item => 
                item && item.scenarioData && 
                item.scenarioData.type === 'bluetooth_scanner'
            );
            
            if (!hasScanner) {
                console.log('NO BLUETOOTH SCANNER');
                window.gameAlert(`You need a Bluetooth scanner to access this ${type}.`, 'error', 'Scanner Required', 4000);
                break;
            }
            
            // Check if we have the required device in our bluetooth scan results
            const bluetoothData = window.gameState?.bluetoothDevices || [];
            const requiredDeviceData = bluetoothData.find(device => 
                device.mac === requiredDevice || device.name === requiredDevice
            );
            
            console.log('BLUETOOTH SCAN DATA', JSON.stringify(bluetoothData));
            console.log('REQUIRED DEVICE CHECK', { required: requiredDevice, found: !!requiredDeviceData });
            
            if (requiredDeviceData) {
                // Check signal strength - need to be close enough
                const minSignalStrength = lockable.minSignalStrength || -70; // dBm
                
                if (requiredDeviceData.signalStrength >= minSignalStrength) {
                    console.log('BLUETOOTH UNLOCK SUCCESS');
                    unlockTarget(lockable, type, lockable.layer);
                    window.gameAlert(`Successfully connected to ${requiredDeviceData.name} and unlocked the ${type}.`, 
                        'success', 'Bluetooth Unlock Successful', 5000);
                } else {
                    console.log('BLUETOOTH SIGNAL TOO WEAK', 
                        `Signal: ${requiredDeviceData.signalStrength}dBm < Required: ${minSignalStrength}dBm`);
                    window.gameAlert(`Bluetooth device detected but signal too weak (${requiredDeviceData.signalStrength}dBm). Move closer.`,
                        'error', 'Weak Signal', 4000);
                }
            } else {
                console.log('BLUETOOTH DEVICE NOT FOUND', 
                    `Required: '${requiredDevice}', Available: ${bluetoothData.map(d => d.name || d.mac).join(", ") || "none"}`);
                window.gameAlert(`This ${type} requires connection to '${requiredDevice}', which hasn't been detected yet.`,
                    'error', 'Device Not Found', 5000);
            }
            break;

        case 'rfid':
            console.log('RFID LOCK UNLOCK ATTEMPT');

            // Support both single card ID (legacy) and array of card IDs
            const requiredCardIds = Array.isArray(lockRequirements.requires) ?
                lockRequirements.requires : [lockRequirements.requires];

            // Check if door accepts UID-only emulation (for DESFire cards)
            const acceptsUIDOnly = lockRequirements.acceptsUIDOnly || false;

            console.log('RFID CARD REQUIRED', requiredCardIds, 'acceptsUIDOnly:', acceptsUIDOnly);

            // Check for keycards in inventory
            const keycards = window.inventory.items.filter(item =>
                item && item.scenarioData &&
                item.scenarioData.type === 'keycard'
            );

            // Check if any physical card matches
            const hasValidCard = keycards.some(card =>
                requiredCardIds.includes(card.scenarioData.card_id || card.scenarioData.key_id)
            );

            // Check for RFID cloner with saved cards
            const cloner = window.inventory.items.find(item =>
                item && item.scenarioData &&
                item.scenarioData.type === 'rfid_cloner'
            );

            const hasCloner = !!cloner;
            const savedCards = cloner?.scenarioData?.saved_cards || [];

            // Check if any saved card matches
            const hasValidClone = savedCards.some(card =>
                requiredCardIds.includes(card.card_id || card.key_id)
            );

            console.log('RFID CHECK', {
                requiredCardIds,
                acceptsUIDOnly,
                hasCloner,
                keycardsCount: keycards.length,
                savedCardsCount: savedCards.length,
                hasValidCard,
                hasValidClone
            });

            if (keycards.length > 0 || savedCards.length > 0) {
                // Start RFID minigame in unlock mode
                window.startRFIDMinigame(lockable, type, {
                    mode: 'unlock',
                    requiredCardIds: requiredCardIds,  // Pass array
                    acceptsUIDOnly: acceptsUIDOnly,
                    availableCards: keycards,
                    hasCloner: hasCloner,
                    onComplete: (success) => {
                        if (success) {
                            setTimeout(() => {
                                unlockTarget(lockable, type, lockable.layer);
                                window.gameAlert('RFID lock unlocked!', 'success', 'Access Granted', 3000);
                            }, 100);
                        }
                    }
                });
            } else {
                console.log('NO RFID CARDS OR CLONER AVAILABLE');
                window.gameAlert('Requires RFID keycard', 'error', 'Access Denied', 4000);
            }
            break;

        default:
            window.gameAlert(`This ${type} requires ${lockRequirements.lockType} to unlock.`, 'info', 'Locked', 4000);
            break;
    }
}

export function getLockRequirementsForDoor(doorSprite) {
    // First, check if the door sprite has lock properties directly
    if (doorSprite.doorProperties) {
        const props = doorSprite.doorProperties;
        if (props.locked) {
            return {
                lockType: props.lockType,
                requires: props.requires,
                keyPins: props.keyPins,  // Include keyPins for scenario-based locks
                difficulty: props.difficulty
            };
        }
    }
    
    // Fallback: Try to find lock requirements from scenario data
    const doorWorldX = doorSprite.x;
    const doorWorldY = doorSprite.y;
    
    const overlappingRooms = [];
    Object.entries(rooms).forEach(([roomId, otherRoom]) => {
        const doorCheckArea = {
            x: doorWorldX - DOOR_ALIGN_OVERLAP,
            y: doorWorldY - DOOR_ALIGN_OVERLAP,
            width: DOOR_ALIGN_OVERLAP * 2,
            height: DOOR_ALIGN_OVERLAP * 2
        };
        
        const roomBounds = {
            x: otherRoom.position.x,
            y: otherRoom.position.y,
            width: otherRoom.map.widthInPixels,
            height: otherRoom.map.heightInPixels
        };
        
        if (boundsOverlap(doorCheckArea, roomBounds)) {
            const roomCenterX = roomBounds.x + (roomBounds.width / 2);
            const roomCenterY = roomBounds.y + (roomBounds.height / 2);
            const player = window.player;
            const distanceToPlayer = player ? Phaser.Math.Distance.Between(
                player.x, player.y,
                roomCenterX, roomCenterY
            ) : 0;
            
            const gameScenario = window.gameScenario;
            const roomData = gameScenario?.rooms?.[roomId];
            
            overlappingRooms.push({
                id: roomId,
                room: otherRoom,
                distance: distanceToPlayer,
                lockType: roomData?.lockType,
                requires: roomData?.requires,
                keyPins: roomData?.keyPins || roomData?.key_pins,  // Include keyPins from scenario (supports both cases)
                difficulty: roomData?.difficulty,
                locked: roomData?.locked
            });
        }
    });
    
    const lockedRooms = overlappingRooms
        .filter(r => r.locked)
        .sort((a, b) => b.distance - a.distance);

    if (lockedRooms.length > 0) {
        const targetRoom = lockedRooms[0];
        return {
            lockType: targetRoom.lockType,
            requires: targetRoom.requires,
            keyPins: targetRoom.keyPins,  // Include keyPins from scenario
            difficulty: targetRoom.difficulty
        };
    }
    
    return null;
}

export function getLockRequirementsForItem(item) {
    if (!item.scenarioData) return null;
    
    return {
        lockType: item.scenarioData.lockType || 'key',
        requires: item.scenarioData.requires || '',
        keyPins: item.scenarioData.keyPins,  // Include keyPins for scenario-based locks
        difficulty: item.scenarioData.difficulty
    };
}

export function unlockTarget(lockable, type, layer) {
    console.log('🔓 unlockTarget called:', { type, lockable });
    
    if (type === 'door') {
        // After unlocking, use the proper door unlock function
        unlockDoor(lockable);
        
        // Emit door unlocked event
        console.log('🔓 Checking for eventDispatcher:', !!window.eventDispatcher);
        if (window.eventDispatcher) {
            const doorProps = lockable.doorProperties || {};
            console.log('🔓 Emitting door_unlocked event:', doorProps);
            window.eventDispatcher.emit('door_unlocked', {
                roomId: doorProps.roomId,
                connectedRoom: doorProps.connectedRoom,
                direction: doorProps.direction,
                lockType: doorProps.lockType
            });
        }
    } else {
        // Handle item unlocking
        if (lockable.scenarioData) {
            lockable.scenarioData.locked = false;
            // Set new state for containers with contents
            if (lockable.scenarioData.contents) {
                lockable.scenarioData.isUnlockedButNotCollected = true;
                
                // Emit item unlocked event
                if (window.eventDispatcher) {
                    window.eventDispatcher.emit('item_unlocked', {
                        itemType: lockable.scenarioData.type,
                        itemName: lockable.scenarioData.name,
                        lockType: lockable.scenarioData.lockType
                    });
                }
                
                // Automatically launch container minigame after unlocking
                setTimeout(() => {
                    if (window.handleContainerInteraction) {
                        console.log('Auto-launching container minigame after unlock');
                        window.handleContainerInteraction(lockable);
                    }
                }, 500); // Small delay to ensure unlock message is shown
                
                return; // Return early to prevent automatic collection
            }
        } else {
            lockable.locked = false;
            if (lockable.contents) {
                lockable.isUnlockedButNotCollected = true;
                
                // Emit item unlocked event
                if (window.eventDispatcher) {
                    window.eventDispatcher.emit('item_unlocked', {
                        itemType: lockable.type || 'unknown',
                        itemName: lockable.name,
                        lockType: lockable.lockType
                    });
                }
                
                // Automatically launch container minigame after unlocking
                setTimeout(() => {
                    if (window.handleContainerInteraction) {
                        console.log('Auto-launching container minigame after unlock');
                        window.handleContainerInteraction(lockable);
                    }
                }, 500); // Small delay to ensure unlock message is shown
                
                return; // Return early to prevent automatic collection
            }
        }
    }
    console.log(`${type} unlocked successfully`);
}

// Export for global access
window.handleUnlock = handleUnlock;
window.getLockRequirementsForDoor = getLockRequirementsForDoor;
window.getLockRequirementsForItem = getLockRequirementsForItem;
window.unlockTarget = unlockTarget;

