// @ts-ignore
import CryptoJS from 'crypto-js';
import * as SecureStore from 'expo-secure-store';
import * as Crypto from 'expo-crypto';

/**
 * Encripta los datos utilizando AES de CryptoJS.
 *
 * @function
 * @param {string} data - Los datos que deseas encriptar.
 * @param {string} secretKey - La clave secreta para encriptar los datos.
 * @returns {string} - El string encriptado en formato Base64.
 *
 * @example
 * import { encryptData } from './encryptData';
 *
 * const secretKey = 'miClaveSecreta';
 * const originalData = 'Hola Mundo';
 * const encryptedData = encryptData(originalData, secretKey);
 * console.log(encryptedData);
 */

export const encryptData = (data: any, key: string) => {
  if (!data) return null;
  const keyDef = CryptoJS.enc.Utf8.parse(key);
  if (!data || !keyDef) {
    throw new Error('Se requiere tanto data como secretKey para encriptar.');
  }
  const encrypted = CryptoJS.AES.encrypt(data, keyDef, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7,
  }).toString();
  return encrypted;
};
export const decryptData = (encryptedData: string, key: string) => {
  if (!encryptedData) return null;

  const keyDef = CryptoJS.enc.Utf8.parse(key);
  if (!keyDef) {
    throw new Error('Se requiere secretKey para desencriptar.');
  }

  try {
    const decrypted = CryptoJS.AES.decrypt(encryptedData, keyDef, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    });

    return decrypted.toString(CryptoJS.enc.Utf8);
  } catch (error) {
    throw new Error('Error al desencriptar los datos.');
  }
};

const saveKey = async (key: string, value: any) => {
  // WHEN_UNLOCKED: Los datos son accesibles mientras el dispositivo esté desbloqueado.
  // WHEN_UNLOCKED_THIS_DEVICE_ONLY: Similar a WHEN_UNLOCKED, pero los datos no se sincronizan con iCloud. Los datos solo estarán disponibles en el dispositivo donde se guardaron, proporcionando una capa extra de seguridad.
  // AFTER_FIRST_UNLOCK: Los datos son accesibles después de que el usuario haya desbloqueado el dispositivo al menos una vez desde el último reinicio.
  // AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: Los datos son accesibles después de que el usuario haya desbloqueado el dispositivo al menos una vez desde el último reinicio. pero los datos permanecen en el dispositivo original (sin sincronización con iCloud).
  try {
    await SecureStore.setItemAsync(key, value, {
      keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
    });
    console.log('Llave guardada de forma segura');
  } catch (error) {
    console.error('Error al guardar la llave:', error);
  }
};

// Leer datos seguros
const getKey = async (key: string) => {
  try {
    const value = await SecureStore.getItemAsync(key);
    return value;
  } catch (error) {
    console.error('Error al leer la llave:', error);
    return false;
  }
};

export const encryptAndStoreValue = async (
  name: string,
  data: any,
  key: string
) => {
  const encryptdata = encryptData(data, key);
  await saveKey(name, encryptdata);
};

export const getEncryptStoreValue = async (name: string, key: string) => {
  const valueEncrypt = (await getKey(name)) as any;
  const value = decryptData(valueEncrypt, key);
  return value;
};

export async function savePassword(name: string, password: string) {
  const hashedPassword = await Crypto.digestStringAsync(
    Crypto.CryptoDigestAlgorithm.SHA256,
    password
  );
  await SecureStore.setItemAsync(name, hashedPassword);
}

export async function isPasswordCorrect(name: string, inputPassword: string) {
  const storedPasswordHash = await SecureStore.getItemAsync(name);
  const inputPasswordHash = await Crypto.digestStringAsync(
    Crypto.CryptoDigestAlgorithm.SHA256,
    inputPassword
  );
  return storedPasswordHash === inputPasswordHash;
}
