import { Injectable, Logger, OnModuleDestroy, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";

/**
 * Prisma service that manages database connection lifecycle
 * Extends PrismaClient to provide connection management and health checks
 */
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
  private readonly logger = new Logger(PrismaService.name);

  constructor() {
    super({
      log: process.env.NODE_ENV === "development" ? ["query", "info", "warn", "error"] : ["error"],
    });
  }

  /**
   * Connect to database when NestJS module initializes
   */
  async onModuleInit() {
    try {
      await this.$connect();
      this.logger.log("Database connection established");
    } catch (error) {
      this.logger.error("Failed to connect to database", error);
      throw error;
    }
  }

  /**
   * Disconnect from database when NestJS module is destroyed
   */
  async onModuleDestroy() {
    await this.$disconnect();
    this.logger.log("Database connection closed");
  }

  /**
   * Health check for database connectivity
   * @returns true if database is accessible, false otherwise
   */
  async isHealthy(): Promise<boolean> {
    try {
      await this.$queryRaw`SELECT 1`;
      return true;
    } catch (error) {
      this.logger.error("Database health check failed", error);
      return false;
    }
  }

  /**
   * Get database connection info for debugging
   * @returns Connection status and basic info
   */
  async getConnectionInfo(): Promise<{
    connected: boolean;
    database?: string;
    version?: string;
  }> {
    try {
      const result = await this.$queryRaw<{ current_database: string; version: string }[]>`
        SELECT current_database(), version()
      `;

      if (result.length > 0 && result[0]) {
        const dbVersion = result[0].version.split(" ")[0];
        return {
          connected: true,
          database: result[0].current_database,
          ...(dbVersion && { version: dbVersion }),
        };
      }

      return { connected: false };
    } catch (error) {
      this.logger.error("Failed to get connection info", error);
      return { connected: false };
    }
  }
}
