import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as crypto from 'crypto';

@Injectable()
export class CredentialEncryptionService {
  private readonly logger = new Logger(CredentialEncryptionService.name);
  private readonly algorithm = 'aes-256-gcm';
  private readonly keyLength = 32;
  private readonly ivLength = 16;
  private readonly tagLength = 16;

  constructor(private readonly config: ConfigService) {}

  private getEncryptionKey(): Buffer {
    const key = this.config.get<string>('CREDENTIAL_ENCRYPTION_KEY');
    if (!key) {
      throw new Error('CREDENTIAL_ENCRYPTION_KEY not configured');
    }
    return crypto.scryptSync(key, 'ai-runtime-salt', this.keyLength);
  }

  /** AES-256-GCM 加密 → base64 */
  encrypt(plaintext: string): string {
    const key = this.getEncryptionKey();
    const iv = crypto.randomBytes(this.ivLength);
    const cipher = crypto.createCipheriv(this.algorithm, key, iv);
    const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
    const tag = cipher.getAuthTag();
    // iv + tag + ciphertext
    const combined = Buffer.concat([iv, tag, encrypted]);
    return combined.toString('base64');
  }

  /** AES-256-GCM 解密 ← base64 */
  decrypt(encoded: string): string {
    const key = this.getEncryptionKey();
    const combined = Buffer.from(encoded, 'base64');
    const iv = combined.subarray(0, this.ivLength);
    const tag = combined.subarray(this.ivLength, this.ivLength + this.tagLength);
    const encrypted = combined.subarray(this.ivLength + this.tagLength);
    const decipher = crypto.createDecipheriv(this.algorithm, key, iv);
    decipher.setAuthTag(tag);
    return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
  }

  /** SHA-256 hash → hex，用于重复检测 */
  hash(plaintext: string): string {
    return crypto.createHash('sha256').update(plaintext).digest('hex');
  }

  /** 脱敏展示：sk-****xxxx */
  mask(plaintext: string): string {
    if (plaintext.length <= 8) {
      return plaintext.substring(0, 2) + '****';
    }
    return plaintext.substring(0, 4) + '****' + plaintext.substring(plaintext.length - 4);
  }

  /** 日志脱敏：移除所有疑似 API Key 的字符串 */
  redact(msg: string): string {
    return msg.replace(/\b(sk-[a-zA-Z0-9]{10,})\b/g, '***REDACTED***');
  }

  logSafe(msg: string): void {
    this.logger.log(this.redact(msg));
  }
}
