/**
 * ============================================================================
 * js/encryption.js - Client-Side End-to-End Encryption Library
 * ============================================================================
 * Handles client-side encryption/decryption for maximum security
 * Uses Web Crypto API for RSA and AES operations
 */

const EncryptionManager = {
    // User's keys (stored in memory during session)
    privateKey: null,
    publicKey: null,
    fingerprint: null,
    
    /**
     * Initialize encryption for current user
     */
    async initialize() {
        try {
            // Check if user has encryption keys
            const response = await $.ajax({
                url: '/api/encryption.php',
                type: 'GET',
                data: { action: 'verify_keys' }
            });
            
            if (!response.has_keys) {
                console.log('No encryption keys found');
                return false;
            }
            
            this.fingerprint = response.fingerprint;
            localStorage.setItem('key_fingerprint', this.fingerprint);
            
            return true;
            
        } catch (error) {
            console.error('Encryption initialization error:', error);
            return false;
        }
    },
    
    /**
     * Generate new encryption keys for user
     */
    async generateKeys(password) {
        if (!password) {
            throw new Error('Password is required');
        }
        
        try {
            const response = await $.ajax({
                url: '/api/encryption.php',
                type: 'POST',
                data: {
                    action: 'generate_keys',
                    password: password
                }
            });
            
            if (response.success) {
                this.fingerprint = response.fingerprint;
                localStorage.setItem('key_fingerprint', this.fingerprint);
                return true;
            }
            
            return false;
            
        } catch (error) {
            console.error('Key generation error:', error);
            throw error;
        }
    },
    
    /**
     * Get recipient's public key
     */
    async getPublicKey(userId) {
        try {
            const response = await $.ajax({
                url: '/api/encryption.php',
                type: 'GET',
                data: {
                    action: 'get_public_key',
                    user_id: userId
                }
            });
            
            if (response.success) {
                return response.public_key;
            }
            
            return null;
            
        } catch (error) {
            console.error('Failed to get public key:', error);
            return null;
        }
    },
    
    /**
     * Convert PEM key to CryptoKey object
     */
    async importRSAPublicKey(pem) {
        // Remove PEM headers
        const pemHeader = "-----BEGIN PUBLIC KEY-----";
        const pemFooter = "-----END PUBLIC KEY-----";
        const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);
        const binaryDer = this.base64ToArrayBuffer(pemContents.replace(/\s/g, ''));
        
        return await window.crypto.subtle.importKey(
            "spki",
            binaryDer,
            {
                name: "RSA-OAEP",
                hash: "SHA-256"
            },
            true,
            ["encrypt"]
        );
    },
    
    /**
     * Convert PEM private key to CryptoKey object
     */
    async importRSAPrivateKey(pem) {
        const pemHeader = "-----BEGIN PRIVATE KEY-----";
        const pemFooter = "-----END PRIVATE KEY-----";
        const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);
        const binaryDer = this.base64ToArrayBuffer(pemContents.replace(/\s/g, ''));
        
        return await window.crypto.subtle.importKey(
            "pkcs8",
            binaryDer,
            {
                name: "RSA-OAEP",
                hash: "SHA-256"
            },
            true,
            ["decrypt"]
        );
    },
    
    /**
     * Encrypt message for recipient
     */
    async encryptMessage(message, recipientPublicKeyPem) {
        try {
            // Generate random AES key
            const aesKey = await window.crypto.subtle.generateKey(
                { name: "AES-CBC", length: 256 },
                true,
                ["encrypt", "decrypt"]
            );
            
            // Generate IV
            const iv = window.crypto.getRandomValues(new Uint8Array(16));
            
            // Encrypt message with AES
            const encoder = new TextEncoder();
            const encryptedMessage = await window.crypto.subtle.encrypt(
                { name: "AES-CBC", iv: iv },
                aesKey,
                encoder.encode(message)
            );
            
            // Export AES key
            const exportedKey = await window.crypto.subtle.exportKey("raw", aesKey);
            
            // Import recipient's RSA public key
            const publicKey = await this.importRSAPublicKey(recipientPublicKeyPem);
            
            // Encrypt AES key with RSA
            const encryptedKey = await window.crypto.subtle.encrypt(
                { name: "RSA-OAEP" },
                publicKey,
                exportedKey
            );
            
            return {
                encrypted_message: this.arrayBufferToBase64(encryptedMessage),
                encrypted_key: this.arrayBufferToBase64(encryptedKey),
                iv: this.arrayBufferToBase64(iv)
            };
            
        } catch (error) {
            console.error('Encryption error:', error);
            throw error;
        }
    },
    
    /**
     * Decrypt message with private key
     */
    async decryptMessage(encryptedData, privateKeyPem) {
        try {
            // Import private key
            const privateKey = await this.importRSAPrivateKey(privateKeyPem);
            
            // Decrypt AES key
            const encryptedKeyBuffer = this.base64ToArrayBuffer(encryptedData.encrypted_key);
            const aesKeyBuffer = await window.crypto.subtle.decrypt(
                { name: "RSA-OAEP" },
                privateKey,
                encryptedKeyBuffer
            );
            
            // Import AES key
            const aesKey = await window.crypto.subtle.importKey(
                "raw",
                aesKeyBuffer,
                { name: "AES-CBC" },
                false,
                ["decrypt"]
            );
            
            // Decrypt message
            const iv = this.base64ToArrayBuffer(encryptedData.iv);
            const encryptedMessage = this.base64ToArrayBuffer(encryptedData.encrypted_message);
            
            const decryptedBuffer = await window.crypto.subtle.decrypt(
                { name: "AES-CBC", iv: iv },
                aesKey,
                encryptedMessage
            );
            
            const decoder = new TextDecoder();
            return decoder.decode(decryptedBuffer);
            
        } catch (error) {
            console.error('Decryption error:', error);
            throw error;
        }
    },
    
    /**
     * Generate SHA-256 hash
     */
    async hashMessage(message) {
        const encoder = new TextEncoder();
        const data = encoder.encode(message);
        const hashBuffer = await window.crypto.subtle.digest('SHA-256', data);
        return this.arrayBufferToHex(hashBuffer);
    },
    
    /**
     * Utility: Base64 to ArrayBuffer
     */
    base64ToArrayBuffer(base64) {
        const binaryString = window.atob(base64);
        const len = binaryString.length;
        const bytes = new Uint8Array(len);
        for (let i = 0; i < len; i++) {
            bytes[i] = binaryString.charCodeAt(i);
        }
        return bytes.buffer;
    },
    
    /**
     * Utility: ArrayBuffer to Base64
     */
    arrayBufferToBase64(buffer) {
        const bytes = new Uint8Array(buffer);
        let binary = '';
        for (let i = 0; i < bytes.byteLength; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
    },
    
    /**
     * Utility: ArrayBuffer to Hex
     */
    arrayBufferToHex(buffer) {
        return Array.from(new Uint8Array(buffer))
            .map(b => b.toString(16).padStart(2, '0'))
            .join('');
    },
    
    /**
     * Show encryption setup modal
     */
    showSetupModal() {
        const modal = `
            <div class="modal fade" id="encryptionSetupModal" tabindex="-1">
                <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                        <div class="modal-header bg-primary text-white">
                            <h5 class="modal-title">
                                <i class="bi bi-shield-lock-fill me-2"></i>
                                Secure Your Messages
                            </h5>
                            <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
                        </div>
                        <div class="modal-body">
                            <div class="text-center mb-4">
                                <i class="bi bi-shield-check text-success" style="font-size: 4rem;"></i>
                            </div>
                            <h6 class="fw-bold mb-3">Enable End-to-End Encryption</h6>
                            <p class="text-muted small">
                                Your messages will be encrypted with military-grade security. 
                                Only you and the recipient can read them - not even server administrators.
                            </p>
                            <div class="alert alert-info small">
                                <i class="bi bi-info-circle me-2"></i>
                                <strong>Important:</strong> Your encryption keys will be protected with your password. 
                                If you forget your password, encrypted messages cannot be recovered.
                            </div>
                            <div class="mb-3">
                                <label class="form-label">Confirm Your Password</label>
                                <input type="password" class="form-control" id="encryptionPassword" 
                                       placeholder="Enter your account password">
                            </div>
                            <div id="encryptionError" class="alert alert-danger d-none"></div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
                                Later
                            </button>
                            <button type="button" class="btn btn-primary" id="enableEncryptionBtn">
                                <i class="bi bi-shield-lock me-2"></i>
                                Enable Encryption
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        `;
        
        $('body').append(modal);
        
        const modalEl = new bootstrap.Modal(document.getElementById('encryptionSetupModal'));
        modalEl.show();
        
        $('#enableEncryptionBtn').on('click', async () => {
            const password = $('#encryptionPassword').val();
            
            if (!password) {
                $('#encryptionError').text('Please enter your password').removeClass('d-none');
                return;
            }
            
            $('#enableEncryptionBtn').prop('disabled', true).html(
                '<span class="spinner-border spinner-border-sm me-2"></span>Generating keys...'
            );
            
            try {
                await EncryptionManager.generateKeys(password);
                
                modalEl.hide();
                
                Toastify({
                    text: "✓ Encryption enabled! Your messages are now secure.",
                    duration: 4000,
                    gravity: "top",
                    position: "center",
                    style: { background: "linear-gradient(to right, #00b09b, #96c93d)" }
                }).showToast();
                
                // Show fingerprint
                setTimeout(() => {
                    EncryptionManager.showFingerprint();
                }, 1000);
                
            } catch (error) {
                $('#encryptionError').text('Failed to enable encryption. Please try again.').removeClass('d-none');
                $('#enableEncryptionBtn').prop('disabled', false).html(
                    '<i class="bi bi-shield-lock me-2"></i>Enable Encryption'
                );
            }
        });
        
        // Cleanup on modal close
        $('#encryptionSetupModal').on('hidden.bs.modal', function () {
            $(this).remove();
        });
    },
    
    /**
     * Show key fingerprint for verification
     */
    showFingerprint() {
        if (!this.fingerprint) {
            this.fingerprint = localStorage.getItem('key_fingerprint');
        }
        
        if (!this.fingerprint) return;
        
        // Format fingerprint in blocks of 4 characters
        const formatted = this.fingerprint.match(/.{1,4}/g).join(' ');
        
        const modal = `
            <div class="modal fade" id="fingerprintModal" tabindex="-1">
                <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                        <div class="modal-header bg-success text-white">
                            <h5 class="modal-title">
                                <i class="bi bi-fingerprint me-2"></i>
                                Your Encryption Fingerprint
                            </h5>
                            <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
                        </div>
                        <div class="modal-body">
                            <p class="text-muted small mb-3">
                                Use this fingerprint to verify you're talking to the right person. 
                                Compare it with your friend over a phone call or in person.
                            </p>
                            <div class="bg-light p-3 rounded text-center mb-3">
                                <code class="text-primary" style="font-size: 0.9rem; word-break: break-all;">
                                    ${formatted}
                                </code>
                            </div>
                            <div class="d-grid gap-2">
                                <button class="btn btn-outline-primary" onclick="EncryptionManager.copyFingerprint()">
                                    <i class="bi bi-clipboard me-2"></i>Copy Fingerprint
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `;
        
        $('body').append(modal);
        const modalEl = new bootstrap.Modal(document.getElementById('fingerprintModal'));
        modalEl.show();
        
        $('#fingerprintModal').on('hidden.bs.modal', function () {
            $(this).remove();
        });
    },
    
    /**
     * Copy fingerprint to clipboard
     */
    copyFingerprint() {
        if (!this.fingerprint) {
            this.fingerprint = localStorage.getItem('key_fingerprint');
        }
        
        navigator.clipboard.writeText(this.fingerprint).then(() => {
            Toastify({
                text: "✓ Fingerprint copied to clipboard",
                duration: 2000,
                gravity: "top",
                position: "center",
                style: { background: "#00b09b" }
            }).showToast();
        });
    }
};

// Initialize on page load
$(document).ready(async function() {
    const hasKeys = await EncryptionManager.initialize();
    
    if (!hasKeys && typeof showEncryptionPrompt !== 'undefined') {
        // Show prompt to enable encryption (optional)
        console.log('Encryption not enabled for this user');
    }
});