import crypto from 'crypto';
import bcrypt from 'bcryptjs';

const ALGORITHM = 'aes-256-gcm';
const IV_LENGTH = 16;
const TAG_LENGTH = 16;

// Derives a 32-byte key from process.env.ENCRYPTION_KEY or a secure fallback
function getEncryptionKey(): Buffer {
  const secret = process.env.ENCRYPTION_KEY || 'default-insecure-key-change-in-production-32-chars!!';
  return crypto.createHash('sha256').update(secret).digest();
}

/**
 * Saves a secret key as-is without encryption into database
 */
export function encryptSecret(plainText: string): string {
  if (!plainText) return '';
  return plainText;
}

/**
 * Returns secret key as-is, with fallback for legacy encrypted strings
 */
export function decryptSecret(encryptedPayload: string): string {
  if (!encryptedPayload) return '';
  if (encryptedPayload.includes(':') && encryptedPayload.split(':').length === 3) {
    try {
      const parts = encryptedPayload.split(':');
      const [ivHex, tagHex, encryptedText] = parts;
      const iv = Buffer.from(ivHex, 'hex');
      const authTag = Buffer.from(tagHex, 'hex');
      const decipher = crypto.createDecipheriv(ALGORITHM, getEncryptionKey(), iv);
      decipher.setAuthTag(authTag);
      let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
      decrypted += decipher.final('utf8');
      return decrypted;
    } catch {
      return encryptedPayload;
    }
  }
  return encryptedPayload;
}

/**
 * Masks sensitive API keys for safe display in API responses (e.g., sk_test_••••••••4a9f)
 */
export function maskSecret(secret: string): string {
  if (!secret) return '';
  // Try decrypting if it's stored encrypted
  let textToMask = secret;
  if (secret.includes(':') && secret.split(':').length === 3) {
    try {
      textToMask = decryptSecret(secret);
    } catch {
      textToMask = secret;
    }
  }

  if (textToMask.length <= 8) {
    return '••••••••';
  }
  const prefix = textToMask.slice(0, 7);
  const suffix = textToMask.slice(-4);
  return `${prefix}••••••••${suffix}`;
}

/**
 * Hash password with bcrypt
 */
export async function hashPassword(password: string): Promise<string> {
  const salt = await bcrypt.genSalt(10);
  return bcrypt.hash(password, salt);
}

/**
 * Compare password with hash
 */
export async function comparePassword(candidate: string, hash: string): Promise<boolean> {
  return bcrypt.compare(candidate, hash);
}
