/**
 * Player Identifier Management
 * 
 * Generates and manages a unique player identifier (UUID) that is stored
 * in localStorage. This identifier is used to sync game states across
 * different domains (hoerdle.de and hördle.de).
 * 
 * Device-specific isolation:
 * - Each device has its own device ID stored in localStorage
 * - Player ID format: {basePlayerId}:{deviceId}
 * - This allows cross-domain sync on the same device while keeping devices isolated
 */

const STORAGE_KEY_PLAYER = 'hoerdle_player_id';
const STORAGE_KEY_DEVICE = 'hoerdle_device_id';

/**
 * Generate a UUID v4
 */
function generateUUID(): string {
    // UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        const r = Math.random() * 16 | 0;
        const v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

/**
 * Get or create a device ID (unique per device)
 * 
 * The device ID is stored in localStorage and persists across sessions.
 * This allows device-specific isolation of game states.
 * 
 * @returns Device identifier (UUID v4)
 */
export function getOrCreateDeviceId(): string {
    if (typeof window === 'undefined') {
        return '';
    }
    
    let deviceId = localStorage.getItem(STORAGE_KEY_DEVICE);
    if (!deviceId) {
        deviceId = generateUUID();
        localStorage.setItem(STORAGE_KEY_DEVICE, deviceId);
    }
    return deviceId;
}

/**
 * Get the device ID without creating a new one
 * 
 * @returns Device identifier or null if not set
 */
export function getDeviceId(): string | null {
    if (typeof window === 'undefined') {
        return null;
    }
    return localStorage.getItem(STORAGE_KEY_DEVICE);
}

/**
 * Generate a base player ID (for cross-domain sync)
 */
function generateBasePlayerId(): string {
    return generateUUID();
}

/**
 * Try to find an existing base player ID from the backend
 * 
 * Extracts the base player ID from a full player ID (format: {basePlayerId}:{deviceId})
 * 
 * @param genreKey - Genre key to search for
 * @returns Base player ID if found, null otherwise
 */
async function findExistingBasePlayerId(genreKey: string): Promise<string | null> {
    try {
        const deviceId = getOrCreateDeviceId();
        const response = await fetch('/api/player-id/suggest', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ genreKey, deviceId }),
        });

        if (response.ok) {
            const data = await response.json();
            if (data.basePlayerId) {
                return data.basePlayerId;
            }
        }
    } catch (error) {
        console.warn('[playerId] Failed to find existing base player ID:', error);
    }
    return null;
}

/**
 * Combine base player ID and device ID into full player ID
 * Format: {basePlayerId}:{deviceId}
 */
function combinePlayerId(basePlayerId: string, deviceId: string): string {
    return `${basePlayerId}:${deviceId}`;
}

/**
 * Extract base player ID from full player ID
 * Format: {basePlayerId}:{deviceId} -> {basePlayerId}
 */
function extractBasePlayerId(fullPlayerId: string): string {
    const colonIndex = fullPlayerId.indexOf(':');
    if (colonIndex === -1) {
        // Legacy format (no device ID) - return as is
        return fullPlayerId;
    }
    return fullPlayerId.substring(0, colonIndex);
}

/**
 * Get or create a player identifier
 * 
 * Player ID format: {basePlayerId}:{deviceId}
 * 
 * If no identifier exists in localStorage, tries to find an existing base player ID
 * from the backend (for cross-domain sync). If none found, generates a new base ID.
 * The device ID is always device-specific.
 * 
 * This enables:
 * - Cross-domain synchronization on the same device (same base player ID)
 * - Device isolation (different device IDs)
 * 
 * @param genreKey - Optional genre key to search for existing base player ID
 * @returns Full player identifier ({basePlayerId}:{deviceId})
 */
export async function getOrCreatePlayerIdAsync(genreKey?: string): Promise<string> {
    if (typeof window === 'undefined') {
        return '';
    }
    
    // Always get/create device ID (device-specific)
    const deviceId = getOrCreateDeviceId();
    
    // Try to get base player ID from localStorage
    let basePlayerId = localStorage.getItem(STORAGE_KEY_PLAYER);
    
    if (!basePlayerId) {
        // Try to find an existing base player ID from backend if genreKey is provided
        if (genreKey) {
            const existingBaseId = await findExistingBasePlayerId(genreKey);
            if (existingBaseId) {
                basePlayerId = existingBaseId;
                localStorage.setItem(STORAGE_KEY_PLAYER, basePlayerId);
            }
        }
        
        // Generate new base player ID if no existing one found
        if (!basePlayerId) {
            basePlayerId = generateBasePlayerId();
            localStorage.setItem(STORAGE_KEY_PLAYER, basePlayerId);
        }
    }
    
    // Combine base player ID with device ID
    return combinePlayerId(basePlayerId, deviceId);
}

/**
 * Get or create a player identifier (synchronous version)
 * 
 * This is the legacy synchronous version. For cross-domain sync, use getOrCreatePlayerIdAsync instead.
 * 
 * @returns Full player identifier ({basePlayerId}:{deviceId})
 */
export function getOrCreatePlayerId(): string {
    if (typeof window === 'undefined') {
        return '';
    }
    
    const deviceId = getOrCreateDeviceId();
    let basePlayerId = localStorage.getItem(STORAGE_KEY_PLAYER);
    
    if (!basePlayerId) {
        basePlayerId = generateBasePlayerId();
        localStorage.setItem(STORAGE_KEY_PLAYER, basePlayerId);
    }
    
    return combinePlayerId(basePlayerId, deviceId);
}

/**
 * Get the current player identifier without creating a new one
 * 
 * @returns Full player identifier ({basePlayerId}:{deviceId}) or null if not set
 */
export function getPlayerId(): string | null {
    if (typeof window === 'undefined') {
        return null;
    }
    
    const deviceId = getDeviceId();
    const basePlayerId = localStorage.getItem(STORAGE_KEY_PLAYER);
    
    if (!deviceId || !basePlayerId) {
        return null;
    }
    
    return combinePlayerId(basePlayerId, deviceId);
}

/**
 * Get base player ID (for debugging/logging)
 * 
 * @returns Base player ID or null if not set
 */
export function getBasePlayerId(): string | null {
    if (typeof window === 'undefined') {
        return null;
    }
    return localStorage.getItem(STORAGE_KEY_PLAYER);
}

