import AsyncStorage from '@react-native-async-storage/async-storage';
import * as LocalAuthentication from 'expo-local-authentication';
import { Platform } from 'react-native';

/**
 * Maneja la autenticación biométrica (Face ID o huella).
 * @returns {Promise<boolean>} Retorna `true` si la autenticación es exitosa, `false` en caso contrario.
 */
export const handleBiometricAuth = async () => {
  // 1. Verificar si el hardware del dispositivo es compatible
  const isCompatible = await LocalAuthentication.hasHardwareAsync();
  if (!isCompatible) {
    return {
      success: false,
      message: 'Dispositivo no compatible con biometría',
      code: 'BiometricNotSupported',
      error: null,
    };
  }

  // 2. Verificar si hay huellas o rostros registrados en el dispositivo
  const isEnrolled = await LocalAuthentication.isEnrolledAsync();
  if (!isEnrolled) {
    // Alert.alert(
    //   'Autenticación Biométrica',
    //   'No tienes ninguna credencial biométrica guardada. Por favor, configura Face ID o tu huella en los ajustes de tu dispositivo.'
    // );
    return {
      success: false,
      message: 'No hay credenciales biométricas registradas',
      code: 'BiometricNotEnrolled',
      error: null,
    };
  }

  // 3. Iniciar la autenticación
  const { success } = await LocalAuthentication.authenticateAsync({
    promptMessage: 'Autentícate para acceder a tu certificado', // Mensaje que se muestra en el diálogo
    cancelLabel: 'Cancelar', // Texto del botón de cancelar (opcional en Android)
    disableDeviceFallback: false, // Evita que se pueda usar el código del dispositivo como alternativa
  });

  if (success) {
    // console.log('¡Autenticación exitosa! ✅');
    return {
      success: true,
      message: 'Autenticación exitosa',
      code: 'BiometricSuccess',
      error: null,
    };
  } else {
    // console.log('Autenticación fallida. ❌');
    return {
      success: false,
      message: 'Autenticación fallida',
      code: 'BiometricFailed',
      error: null,
    };
  }
};

// Usamos una clave constante para evitar errores de tipeo
const BIOMETRIC_USERS_KEY = 'APACUANA_BIOMETRIC_ENABLED_USERS';

/**
 * Agrega un userId a la lista de usuarios con biometría habilitada.
 * @param {string} userId - El ID del usuario a agregar.
 */
export const addUserWithBiometrics = async (userId: string) => {
  try {
    // 1. Obtener la lista existente
    const existingUsers = await AsyncStorage.getItem(BIOMETRIC_USERS_KEY);
    const users = existingUsers ? JSON.parse(existingUsers) : [];

    // 2. Agregar el nuevo userId solo si no está ya en la lista
    if (!users.includes(userId)) {
      users.push(userId);
      // 3. Guardar la lista actualizada en formato string
      await AsyncStorage.setItem(BIOMETRIC_USERS_KEY, JSON.stringify(users));
      // console.log(`✅ Usuario ${userId} agregado a la lista de biometría.`);
      return {
        success: true,
        message: 'Usuario agregado a la lista de biometría',
        code: 'BiometricUserAdded',
        error: null,
      };
    } else {
      // console.log(`ℹ️ El usuario ${userId} ya estaba en la lista.`);
      return {
        success: false,
        message: 'El usuario ya estaba en la lista de biometría',
        code: 'BiometricUserAlreadyExists',
        error: null,
      };
    }
  } catch (error) {
    console.error(
      '[ApacuanaSDKError]: Error al guardar el usuario con biometría:',
      error
    );
    return {
      success: false,
      message: 'Error al guardar el usuario con biometría',
      code: 'BiometricStorageError',
      error: error,
    };
  }
};

/**
 * Elimina un userId de la lista de usuarios con biometría habilitada.
 * @param {string} userId - El ID del usuario a eliminar.
 */
export const removeUserWithBiometrics = async (userId: string) => {
  if (!userId) {
    return {
      success: false,
      message: 'userId no proporcionado',
      code: 'BiometricInvalidUserId',
      error: null,
    };
  }

  try {
    // 1. Obtener la lista existente
    const existingUsers = await AsyncStorage.getItem(BIOMETRIC_USERS_KEY);
    let users = existingUsers ? JSON.parse(existingUsers) : [];

    // 2. Filtrar la lista para excluir el userId
    const updatedUsers = users.filter((id: string) => id !== userId);

    // 3. Guardar la nueva lista actualizada
    await AsyncStorage.setItem(
      BIOMETRIC_USERS_KEY,
      JSON.stringify(updatedUsers)
    );
    // console.log(`✅ Usuario ${userId} eliminado de la lista de biometría.`);
    return {
      success: true,
      message: 'Usuario eliminado de la lista de biometría',
      code: 'BiometricUserRemoved',
      error: null,
    };
  } catch (error) {
    // console.error('Error al eliminar el usuario con biometría:', error);
    return {
      success: false,
      message: 'Error al eliminar el usuario con biometría',
      code: 'BiometricUserRemovalError',
      error: error,
    };
  }
};

/**
 * Obtiene la lista de todos los userIds con biometría habilitada.
 * @returns {Promise<string[]>} Una promesa que resuelve a un array de userIds.
 */
export const getUsersWithBiometrics = async () => {
  try {
    const users = await AsyncStorage.getItem(BIOMETRIC_USERS_KEY);
    return users ? JSON.parse(users) : [];
  } catch (error) {
    console.error('Error al obtener los usuarios con biometría:', error);
    return [];
  }
};

/**
 * Verifica si un usuario específico tiene la biometría habilitada.
 * @param {string} userId - El ID del usuario a verificar.
 * @returns {Promise<boolean>} Retorna `true` si el usuario tiene biometría, `false` en caso contrario.
 */
export const isBiometricEnabledForUser = async (userId: string) => {
  if (!userId) {
    return {
      success: false,
      message: 'userId no proporcionado',
      code: 'BiometricInvalidUserId',
      error: null,
    };
  }

  try {
    const isCompatible = await LocalAuthentication.hasHardwareAsync();
    if (!isCompatible) {
      return {
        success: false,
        message: 'Dispositivo no compatible con biometría',
        code: 'BiometricNotSupported',
        error: null,
      };
    }

    // 2. Verificar si hay huellas o rostros registrados en el dispositivo
    const isEnrolled = await LocalAuthentication.isEnrolledAsync();
    if (!isEnrolled) {
      return {
        success: false,
        message: 'No hay credenciales biométricas registradas',
        code: 'BiometricNotEnrolled',
        error: null,
      };
    }
    // 1. Obtiene la lista completa de usuarios con biometría
    const usersWithBiometrics = await getUsersWithBiometrics();

    // 2. Comprueba si el userId actual está en esa lista
    return {
      success: true,
      message: 'Verificación exitosa',
      code: 'BiometricCheckSuccess',
      error: null,
      isEnabled: usersWithBiometrics.includes(userId),
    };
  } catch (error) {
    console.error('Error al verificar la biometría para el usuario:', error);
    return {
      success: false,
      message: 'Error al verificar la biometría para el usuario',
      code: 'BiometricCheckError',
      error: error,
    };
  }
};

export const isBiometricEnabled = async () => {
  try {
    const isCompatible = await LocalAuthentication.hasHardwareAsync();
    if (!isCompatible) {
      return {
        success: false,
        message: 'Dispositivo no compatible con biometría',
        code: 'BiometricNotSupported',
        error: null,
      };
    }

    // 2. Verificar si hay huellas o rostros registrados en el dispositivo
    const isEnrolled = await LocalAuthentication.isEnrolledAsync();
    if (!isEnrolled) {
      return {
        success: false,
        message: 'No hay credenciales biométricas registradas',
        code: 'BiometricNotEnrolled',
        error: null,
      };
    }
    return true;
  } catch (error) {
    console.error('Error al verificar la biometría:', error);
    return {
      success: false,
      message: 'Error al verificar la biometría',
      code: 'BiometricCheckError',
      error: error,
    };
  }
};

/**
 * Verifica el tipo de hardware biométrico disponible en el dispositivo.
 * Da prioridad a Face ID si ambos estuvieran disponibles (algo muy improbable).
 * * @returns {Promise<'Face ID' | 'Touch ID' | false>} Una promesa que se resuelve a:
 * - "Face ID" si el dispositivo soporta reconocimiento facial.
 * - "Touch ID" si el dispositivo soporta huella digital.
 * - false si no soporta ninguno, no tiene hardware, o si ocurre un error.
 */
export const getBiometricType = async (): Promise<
  'Face ID' | 'Touch ID' | false
> => {
  try {
    if (Platform.OS === 'android') return 'Touch ID';
    // Primero, verificamos que el dispositivo tenga CUALQUIER hardware biométrico.
    const hasHardware = await LocalAuthentication.hasHardwareAsync();
    if (!hasHardware) {
      return false;
    }

    // Si tiene hardware, verificamos qué tipos específicos soporta.
    const supportedTypes =
      await LocalAuthentication.supportedAuthenticationTypesAsync();

    // Damos prioridad a Face ID, ya que es el método más moderno en dispositivos Apple.
    if (
      supportedTypes.includes(
        LocalAuthentication.AuthenticationType.FACIAL_RECOGNITION
      )
    ) {
      return 'Face ID';
    }

    // Si no tiene Face ID, verificamos si tiene lector de huella.
    if (
      supportedTypes.includes(
        LocalAuthentication.AuthenticationType.FINGERPRINT
      )
    ) {
      return 'Touch ID';
    }

    // Si tiene hardware pero no es de un tipo conocido (muy raro), retornamos false.
    return false;
  } catch (error) {
    console.error('Error al verificar el tipo de biometría:', error);
    // Si hay algún error durante la comprobación, asumimos que no hay biometría disponible.
    return false;
  }
};
