import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } from 'node:crypto';
import { config } from './config';

const encryptionKey = createHash('sha256').update(`guardian-phone:${config.contactDataSecret}`).digest();
const paymentEncryptionKey = createHash('sha256').update(`payment-asset:${config.contactDataSecret}`).digest();
const identityDocumentEncryptionKey = createHash('sha256')
  .update(`identity-document:${config.contactDataSecret}`).digest();
const certificateEncryptionKey = createHash('sha256')
  .update(`journey-certificate:${config.contactDataSecret}`).digest();
const accessLogEncryptionKey = createHash('sha256')
  .update(`access-log:${config.contactDataSecret}`).digest();

export const protectContactHash = (clientHash: string): string =>
  createHmac('sha256', config.contactDataSecret).update(clientHash.toLowerCase()).digest('hex');

export const contactFingerprintKey = (invitationId: string): string =>
  createHmac('sha256', config.contactDataSecret)
    .update(`guardian-contact-v2:${invitationId}`).digest('base64url');

const encryptWithKey = (value: string, key: Buffer): string => {
  const iv = randomBytes(12);
  const cipher = createCipheriv('aes-256-gcm', key, iv);
  const encrypted = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]);
  return `${iv.toString('base64url')}.${cipher.getAuthTag().toString('base64url')}.${encrypted.toString('base64url')}`;
};

const decryptWithKey = (value: string, key: Buffer): string => {
  const [iv, tag, encrypted] = value.split('.');
  if (!iv || !tag || !encrypted) throw new Error('Invalid encrypted value');
  const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(iv, 'base64url'));
  decipher.setAuthTag(Buffer.from(tag, 'base64url'));
  return Buffer.concat([decipher.update(Buffer.from(encrypted, 'base64url')), decipher.final()]).toString('utf8');
};

export const encryptSensitive = (value: string): string => encryptWithKey(value, encryptionKey);
export const decryptSensitive = (value: string): string => decryptWithKey(value, encryptionKey);
export const encryptPaymentAsset = (value: string): string => encryptWithKey(value, paymentEncryptionKey);
export const decryptPaymentAsset = (value: string): string => decryptWithKey(value, paymentEncryptionKey);
export const encryptIdentityDocument = (value: string): string =>
  encryptWithKey(value, identityDocumentEncryptionKey);
export const decryptIdentityDocument = (value: string): string =>
  decryptWithKey(value, identityDocumentEncryptionKey);
export const encryptCertificateDocument = (value: string): string =>
  encryptWithKey(value, certificateEncryptionKey);
export const decryptCertificateDocument = (value: string): string =>
  decryptWithKey(value, certificateEncryptionKey);
export const encryptAccessAddress = (value: string): string =>
  encryptWithKey(value, accessLogEncryptionKey);
export const decryptAccessAddress = (value: string): string =>
  decryptWithKey(value, accessLogEncryptionKey);
export const hashAccessAddress = (value: string): string =>
  createHmac('sha256', config.contactDataSecret).update(`access-address:${value}`).digest('hex');
