import { Injectable, type OnModuleInit, type OnModuleDestroy } from '@nestjs/common';
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from '@prisma/client';
import pg from 'pg';
import { encryptField, decryptField, type FieldEncryptionConfig } from './field-encryption';

function getKycEncryptionConfig(): FieldEncryptionConfig | null {
  const key = process.env['KYC_ENCRYPTION_KEY'];
  if (!key) return null;
  return {
    key,
    keyVersion: Number(process.env['KYC_ENCRYPTION_KEY_VERSION'] ?? '1'),
  };
}

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
  private pool: pg.Pool;
  private kycEncryption: FieldEncryptionConfig | null;

  constructor() {
    const pool = new pg.Pool({ connectionString: process.env['DATABASE_URL'] });
    const adapter = new PrismaPg(pool);
    super({ adapter });
    this.pool = pool;
    this.kycEncryption = getKycEncryptionConfig();
  }

  /** Encrypt kycData before writing to the database. */
  encryptKycData(data: unknown): unknown {
    if (!this.kycEncryption || data === null || data === undefined) return data;
    return encryptField(data, this.kycEncryption);
  }

  /** Decrypt kycData after reading from the database. */
  decryptKycData(data: unknown): unknown {
    if (!this.kycEncryption || data === null || data === undefined) return data;
    return decryptField(data, this.kycEncryption);
  }

  async onModuleInit(): Promise<void> {
    await this.$connect();
  }

  async onModuleDestroy(): Promise<void> {
    await this.$disconnect();
    await this.pool.end();
  }
}
