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 { createEncryptionExtension } from './encryption-middleware';
import { FieldEncryptionService } from './field-encryption.service';
import { LoggerService } from './logger.service';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
  private pool: pg.Pool;
  readonly fieldEncryption: FieldEncryptionService;

  /**
   * Extended client with encryption middleware applied.
   * Use `this.encrypted` for all operations that should transparently
   * encrypt/decrypt PII fields. For raw/unencrypted access use `this` directly.
   */
  readonly encrypted: ReturnType<typeof PrismaClient.prototype.$extends>;

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

    // Initialize field encryption service and create extended client
    this.fieldEncryption = new FieldEncryptionService(this.logger);
    this.encrypted = this.$extends(createEncryptionExtension(this.fieldEncryption));
  }

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

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