import { Injectable } from '@nestjs/common';
import {
  HealthIndicator,
  HealthIndicatorResult,
} from '@nestjs/terminus';
import { PrismaService } from '../prisma/prisma.service';

interface ModuleStatus {
  name: string;
  status: 'up' | 'down' | 'degraded';
  tables?: number;
  message?: string;
}

/**
 * Health indicator that reports the status of application modules
 * by checking their associated database tables.
 */
@Injectable()
export class ModulesHealthIndicator extends HealthIndicator {
  constructor(private readonly prisma: PrismaService) {
    super();
  }

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    const moduleStatuses: ModuleStatus[] = [];
    let overallStatus: 'up' | 'degraded' = 'up';

    // Check core modules
    const coreStatus = await this.checkCoreModule();
    moduleStatuses.push(coreStatus);
    if (coreStatus.status !== 'up') overallStatus = 'degraded';

    // Check HR module
    const hrStatus = await this.checkHrModule();
    moduleStatuses.push(hrStatus);
    if (hrStatus.status !== 'up') overallStatus = 'degraded';

    // Check LEAN module
    const leanStatus = await this.checkLeanModule();
    moduleStatuses.push(leanStatus);
    if (leanStatus.status !== 'up') overallStatus = 'degraded';

    // Check Integrations module
    const integrationsStatus = await this.checkIntegrationsModule();
    moduleStatuses.push(integrationsStatus);
    if (integrationsStatus.status !== 'up') overallStatus = 'degraded';

    return this.getStatus(key, overallStatus === 'up', {
      status: overallStatus,
      modules: moduleStatuses,
    });
  }

  private async checkCoreModule(): Promise<ModuleStatus> {
    try {
      const [users, departments, roles] = await Promise.all([
        this.prisma.user.count(),
        this.prisma.department.count(),
        this.prisma.role.count(),
      ]);

      return {
        name: 'core',
        status: 'up',
        message: `Users: ${users}, Departments: ${departments}, Roles: ${roles}`,
      };
    } catch (error) {
      return {
        name: 'core',
        status: 'down',
        message: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  private async checkHrModule(): Promise<ModuleStatus> {
    try {
      const [employees, absences, timeEntries] = await Promise.all([
        this.prisma.employee.count(),
        this.prisma.absence.count(),
        this.prisma.timeEntry.count(),
      ]);

      return {
        name: 'hr',
        status: 'up',
        message: `Employees: ${employees}, Absences: ${absences}, TimeEntries: ${timeEntries}`,
      };
    } catch (error) {
      return {
        name: 'hr',
        status: 'down',
        message: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  private async checkLeanModule(): Promise<ModuleStatus> {
    try {
      const [s3Plans, skills, meetings] = await Promise.all([
        this.prisma.s3Plan.count(),
        this.prisma.skill.count(),
        this.prisma.morningMeeting.count(),
      ]);

      return {
        name: 'lean',
        status: 'up',
        message: `S3Plans: ${s3Plans}, Skills: ${skills}, Meetings: ${meetings}`,
      };
    } catch (error) {
      return {
        name: 'lean',
        status: 'down',
        message: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  private async checkIntegrationsModule(): Promise<ModuleStatus> {
    try {
      const [credentials, syncHistory] = await Promise.all([
        this.prisma.integrationCredential.count(),
        this.prisma.integrationSyncHistory.count(),
      ]);

      return {
        name: 'integrations',
        status: 'up',
        message: `Credentials: ${credentials}, SyncHistory: ${syncHistory}`,
      };
    } catch (error) {
      return {
        name: 'integrations',
        status: 'down',
        message: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }
}
