import { Controller, Get, Inject, Optional } from '@nestjs/common';
import { ApiTags, ApiOperation } from '@nestjs/swagger';
import { Public } from '../common/decorators/public.decorator';
import { CrmPrismaService } from '../prisma/crm-prisma.service';
import { RedisService } from '../redis/redis.service';
import { LexwareClientService } from '../lexware/lexware-client.service';

interface HealthResponse {
  status: 'ok' | 'error';
  service: string;
  timestamp: string;
  version: string;
  services: {
    database: 'up' | 'down';
    redis: 'up' | 'down';
    lexware: 'up' | 'down' | 'unconfigured';
  };
}

@ApiTags('Health')
@Controller('health')
export class HealthController {
  constructor(
    private readonly prisma: CrmPrismaService,
    private readonly redis: RedisService,
    @Optional() @Inject(LexwareClientService)
    private readonly lexwareClient?: LexwareClientService,
  ) {}

  @Get()
  @Public()
  @ApiOperation({ summary: 'Health-Check fuer CRM-Service' })
  async check(): Promise<HealthResponse> {
    const [dbStatus, redisStatus, lexwareStatus] = await Promise.allSettled([
      this.checkDatabase(),
      this.checkRedis(),
      this.checkLexware(),
    ]);

    const dbOk = dbStatus.status === 'fulfilled' && dbStatus.value;
    const redisOk = redisStatus.status === 'fulfilled' && redisStatus.value;
    const lexwareResult: 'up' | 'down' | 'unconfigured' =
      lexwareStatus.status === 'fulfilled'
        ? lexwareStatus.value
        : 'down';

    // Lexware "unconfigured" ist kein Fehler
    const allUp = dbOk && redisOk && lexwareResult !== 'down';

    return {
      status: allUp ? 'ok' : 'error',
      service: 'crm-service',
      timestamp: new Date().toISOString(),
      version: '0.2.0',
      services: {
        database: dbOk ? 'up' : 'down',
        redis: redisOk ? 'up' : 'down',
        lexware: lexwareResult,
      },
    };
  }

  private async checkDatabase(): Promise<boolean> {
    try {
      await this.prisma.$queryRaw`SELECT 1`;
      return true;
    } catch {
      return false;
    }
  }

  private async checkRedis(): Promise<boolean> {
    try {
      const pong = await this.redis.ping();
      return pong === 'PONG';
    } catch {
      return false;
    }
  }

  private async checkLexware(): Promise<'up' | 'down' | 'unconfigured'> {
    if (!this.lexwareClient) return 'unconfigured';
    return this.lexwareClient.isHealthy();
  }
}
