/**
 * Biometric Authentication Utility
 * Supports Face ID, Touch ID, Windows Hello, and Android Biometric
 */

// Check if biometric authentication is available
export const isBiometricAvailable = async () => {
  // Check if browser supports Web Authentication API
  if (!window.PublicKeyCredential) {
    return false;
  }

  try {
    // Check if platform authenticator is available (Face ID, Touch ID, etc.)
    const available =
      await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
    return available;
  } catch (error) {
    // Silently fail for production
    return false;
  }
};

// Get biometric type description
export const getBiometricType = () => {
  const ua = navigator.userAgent;

  if (/iPhone|iPad|iPod/.test(ua)) {
    // iOS devices - could be Face ID or Touch ID
    return "Biometric Authentication";
  } else if (/Android/.test(ua)) {
    return "Biometric Authentication";
  } else if (/Windows/.test(ua)) {
    return "Biometric Authentication";
  } else if (/Mac/.test(ua)) {
    return "Biometric Authentication";
  }

  return "Biometric Authentication";
};

// Register biometric credential
export const registerBiometric = async (username, userId) => {
  try {
    // Generate challenge from server (in production, get this from server)
    const challenge = new Uint8Array(32);
    crypto.getRandomValues(challenge);

    const publicKeyCredentialCreationOptions = {
      challenge,
      rp: {
        name: "HOP Worship Platform",
        id: window.location.hostname,
      },
      user: {
        id: new TextEncoder().encode(userId.toString()),
        name: username,
        displayName: username,
      },
      pubKeyCredParams: [
        { alg: -7, type: "public-key" }, // ES256
        { alg: -257, type: "public-key" }, // RS256
      ],
      authenticatorSelection: {
        authenticatorAttachment: "platform", // Use platform authenticator (Face ID, Touch ID, etc.)
        userVerification: "required",
        requireResidentKey: false,
      },
      timeout: 60000,
      attestation: "none",
    };

    const credential = await navigator.credentials.create({
      publicKey: publicKeyCredentialCreationOptions,
    });

    // Convert credential to base64 for storage
    const credentialData = {
      id: credential.id,
      rawId: arrayBufferToBase64(credential.rawId),
      type: credential.type,
      response: {
        attestationObject: arrayBufferToBase64(
          credential.response.attestationObject,
        ),
        clientDataJSON: arrayBufferToBase64(credential.response.clientDataJSON),
      },
    };

    return credentialData;
  } catch (error) {
    console.error("Biometric registration error:", error);
    throw new Error(getBiometricErrorMessage(error));
  }
};

// Authenticate using biometric
export const authenticateWithBiometric = async (credentialId) => {
  try {
    // Generate challenge
    const challenge = new Uint8Array(32);
    crypto.getRandomValues(challenge);

    const publicKeyCredentialRequestOptions = {
      challenge,
      allowCredentials: credentialId
        ? [
            {
              id: base64ToArrayBuffer(credentialId),
              type: "public-key",
              transports: ["internal"],
            },
          ]
        : [],
      userVerification: "required",
      timeout: 60000,
    };

    const assertion = await navigator.credentials.get({
      publicKey: publicKeyCredentialRequestOptions,
    });

    // Convert assertion to base64
    const assertionData = {
      id: assertion.id,
      rawId: arrayBufferToBase64(assertion.rawId),
      type: assertion.type,
      response: {
        authenticatorData: arrayBufferToBase64(
          assertion.response.authenticatorData,
        ),
        clientDataJSON: arrayBufferToBase64(assertion.response.clientDataJSON),
        signature: arrayBufferToBase64(assertion.response.signature),
        userHandle: assertion.response.userHandle
          ? arrayBufferToBase64(assertion.response.userHandle)
          : null,
      },
    };

    return assertionData;
  } catch (error) {
    console.error("Biometric authentication error:", error);
    throw new Error(getBiometricErrorMessage(error));
  }
};

// Helper: Convert ArrayBuffer to Base64
function arrayBufferToBase64(buffer) {
  const bytes = new Uint8Array(buffer);
  let binary = "";
  for (let i = 0; i < bytes.byteLength; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary);
}

// Helper: Convert Base64 to ArrayBuffer
function base64ToArrayBuffer(base64) {
  const binary = atob(base64);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  return bytes.buffer;
}

// Get user-friendly error message
function getBiometricErrorMessage(error) {
  if (error.name === "NotAllowedError") {
    return "Biometric authentication was cancelled";
  } else if (error.name === "NotSupportedError") {
    return "Biometric authentication is not supported on this device";
  } else if (error.name === "SecurityError") {
    return "Biometric authentication failed due to security restrictions";
  } else if (error.name === "AbortError") {
    return "Biometric authentication was aborted";
  } else if (error.name === "InvalidStateError") {
    return "Biometric credential already registered";
  } else if (error.name === "NotReadableError") {
    return "Biometric sensor is not readable";
  }
  return error.message || "Biometric authentication failed";
}

// Store biometric credential ID locally
export const storeBiometricCredential = (username, credentialId) => {
  const credentials = getBiometricCredentials();
  credentials[username] = credentialId;
  localStorage.setItem("biometric_credentials", JSON.stringify(credentials));
};

// Get biometric credential ID for user
export const getBiometricCredential = (username) => {
  const credentials = getBiometricCredentials();
  return credentials[username] || null;
};

// Get all stored biometric credentials
export const getBiometricCredentials = () => {
  const stored = localStorage.getItem("biometric_credentials");
  return stored ? JSON.parse(stored) : {};
};

// Remove biometric credential
export const removeBiometricCredential = (username) => {
  const credentials = getBiometricCredentials();
  delete credentials[username];
  localStorage.setItem("biometric_credentials", JSON.stringify(credentials));
};

// Check if user has biometric registered
export const hasBiometricRegistered = (username) => {
  return getBiometricCredential(username) !== null;
};
