import { Injectable } from '@nestjs/common';
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';

@Injectable()
export class EncryptionService {
  private readonly key = createHash('sha256')
    .update(process.env.DATA_ENCRYPTION_KEY ?? 'local-development-data-encryption-key')
    .digest();

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

  looksEncrypted(value: string): boolean {
    const parts = value.split('.');
    if (parts.length !== 3) return false;
    const [ivRaw, authTagRaw, encryptedRaw] = parts;
    if (!ivRaw || !authTagRaw || !encryptedRaw) return false;
    try {
      Buffer.from(ivRaw, 'base64url');
      Buffer.from(authTagRaw, 'base64url');
      Buffer.from(encryptedRaw, 'base64url');
      return true;
    } catch {
      return false;
    }
  }

  decrypt(value: string): string {
    const [ivRaw, authTagRaw, encryptedRaw] = value.split('.');
    if (!ivRaw || !authTagRaw || !encryptedRaw) {
      throw new Error('Некорректный формат зашифрованных данных');
    }
    const decipher = createDecipheriv('aes-256-gcm', this.key, Buffer.from(ivRaw, 'base64url'));
    decipher.setAuthTag(Buffer.from(authTagRaw, 'base64url'));
    const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedRaw, 'base64url')), decipher.final()]);
    return decrypted.toString('utf8');
  }

  decryptIfNeeded(value: string): string {
    if (!this.looksEncrypted(value)) {
      return value;
    }
    try {
      return this.decrypt(value);
    } catch {
      return value;
    }
  }
}
