/**
 * Encryption utilities for sensitive data storage
 * Adapted for admin panel with Web Crypto API
 */

/**
 * Simple encryption using Web Crypto API
 */
export async function encryptData(data: string, key: string): Promise<string> {
  if (typeof window === 'undefined' || !window.crypto) {
    // Fallback for Node.js or environments without crypto
    return btoa(data); // Base64 encoding (not secure, but better than plaintext)
  }

  try {
    // Derive key from password
    const encoder = new TextEncoder();
    const dataBuffer = encoder.encode(data);
    const keyBuffer = encoder.encode(key);

    // Import key
    const cryptoKey = await window.crypto.subtle.importKey(
      'raw',
      keyBuffer,
      { name: 'PBKDF2' },
      false,
      ['deriveBits', 'deriveKey']
    );

    // Derive encryption key
    const derivedKey = await window.crypto.subtle.deriveKey(
      {
        name: 'PBKDF2',
        salt: encoder.encode('admin-panel-salt'),
        iterations: 100000,
        hash: 'SHA-256',
      },
      cryptoKey,
      { name: 'AES-GCM', length: 256 },
      false,
      ['encrypt']
    );

    // Generate IV
    const iv = window.crypto.getRandomValues(new Uint8Array(12));

    // Encrypt
    const encrypted = await window.crypto.subtle.encrypt(
      { name: 'AES-GCM', iv },
      derivedKey,
      dataBuffer
    );

    // Combine IV and encrypted data
    const combined = new Uint8Array(iv.length + encrypted.byteLength);
    combined.set(iv);
    combined.set(new Uint8Array(encrypted), iv.length);

    // Convert to base64
    return btoa(String.fromCharCode(...combined));
  } catch (error) {
    console.error('Encryption failed:', error);
    // Fallback to base64
    return btoa(data);
  }
}

/**
 * Decrypt data
 */
export async function decryptData(encrypted: string, key: string): Promise<string> {
  if (typeof window === 'undefined' || !window.crypto) {
    // Fallback
    try {
      return atob(encrypted);
    } catch {
      throw new Error('Decryption failed');
    }
  }

  try {
    const encoder = new TextEncoder();
    const decoder = new TextDecoder();

    // Decode base64
    const combined = Uint8Array.from(atob(encrypted), (c) => c.charCodeAt(0));

    // Extract IV and encrypted data
    const iv = combined.slice(0, 12);
    const encryptedData = combined.slice(12);

    // Derive key
    const keyBuffer = encoder.encode(key);
    const cryptoKey = await window.crypto.subtle.importKey(
      'raw',
      keyBuffer,
      { name: 'PBKDF2' },
      false,
      ['deriveBits', 'deriveKey']
    );

    const derivedKey = await window.crypto.subtle.deriveKey(
      {
        name: 'PBKDF2',
        salt: encoder.encode('admin-panel-salt'),
        iterations: 100000,
        hash: 'SHA-256',
      },
      cryptoKey,
      { name: 'AES-GCM', length: 256 },
      false,
      ['decrypt']
    );

    // Decrypt
    const decrypted = await window.crypto.subtle.decrypt(
      { name: 'AES-GCM', iv },
      derivedKey,
      encryptedData
    );

    return decoder.decode(decrypted);
  } catch (error) {
    console.error('Decryption failed:', error);
    throw new Error('Decryption failed');
  }
}

/**
 * Secure storage wrapper with encryption
 */
export class SecureStorage {
  private encryptionKey: string;

  constructor() {
    // Generate or retrieve encryption key
    this.encryptionKey = this.getOrCreateEncryptionKey();
  }

  private getOrCreateEncryptionKey(): string {
    if (typeof window === 'undefined') return 'default-key';

    const stored = localStorage.getItem('admin_encryption_key');
    if (stored) {
      return stored;
    }

    // Generate a simple key (in production, use a more secure method)
    const key = `admin_key_${Date.now()}_${Math.random().toString(36).slice(2)}`;
    localStorage.setItem('admin_encryption_key', key);
    return key;
  }

  async setItem(key: string, value: string): Promise<void> {
    if (typeof window === 'undefined') return;

    try {
      const encrypted = await encryptData(value, this.encryptionKey);
      localStorage.setItem(key, encrypted);
    } catch (error) {
      console.error('Failed to encrypt and store:', error);
      // Fallback to plain storage for non-sensitive data
      localStorage.setItem(key, value);
    }
  }

  async getItem(key: string): Promise<string | null> {
    if (typeof window === 'undefined') return null;

    const encrypted = localStorage.getItem(key);
    if (!encrypted) return null;

    try {
      return await decryptData(encrypted, this.encryptionKey);
    } catch (error) {
      console.error('Failed to decrypt:', error);
      // Try as plain text (for migration)
      return encrypted;
    }
  }

  removeItem(key: string): void {
    if (typeof window === 'undefined') return;
    localStorage.removeItem(key);
  }

  clear(): void {
    if (typeof window === 'undefined') return;
    localStorage.clear();
  }
}
