import { Module } from '@nestjs/common';
import { LoggerModule as PinoLoggerModule } from 'nestjs-pino';
import { randomUUID } from 'node:crypto';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { ConfigService } from '@nestjs/config';
import type { Env } from '../config/env.schema';

// CODING-RULES §09 (PGD-OBS-002): redact LGPD agressivo.
// Sempre cobrir: *.cpf, *.cardNumber, *.password, req.headers.authorization, req.headers.cookie.
const REDACT_PATHS = [
  '*.cpf',
  '*.cardNumber',
  '*.password',
  '*.passwordHash',
  '*.token',
  '*.secret',
  'req.headers.authorization',
  'req.headers.cookie',
  'req.headers["set-cookie"]',
  'res.headers["set-cookie"]',
];

@Module({
  imports: [
    PinoLoggerModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService<Env, true>) => {
        const isProd = config.get('NODE_ENV', { infer: true }) === 'production';
        const level = config.get('LOG_LEVEL', { infer: true });
        const serviceName = config.get('OTEL_SERVICE_NAME', { infer: true });

        return {
          pinoHttp: {
            level,
            // pretty em dev; JSON estruturado em prod (Grafana LGTM consumirá).
            transport: isProd
              ? undefined
              : {
                  target: 'pino-pretty',
                  options: {
                    colorize: true,
                    translateTime: 'SYS:HH:MM:ss.l',
                    ignore: 'pid,hostname,req,res,responseTime',
                    messageFormat: '{msg} {req.method} {req.url} {res.statusCode} ({responseTime}ms)',
                  },
                },
            redact: {
              paths: REDACT_PATHS,
              censor: '[REDACTED]',
            },
            // Correlation ID: respeita header upstream ou gera UUID v4.
            genReqId: (req: IncomingMessage, res: ServerResponse) => {
              const headerVal =
                req.headers['x-request-id'] ??
                req.headers['x-correlation-id'] ??
                req.headers['traceparent'];
              const id = typeof headerVal === 'string' && headerVal.length > 0 ? headerVal : randomUUID();
              res.setHeader('x-request-id', id);
              return id;
            },
            customProps: () => ({ service: serviceName }),
            // Reduz ruído em health checks.
            customLogLevel: (_req, res, err) => {
              if (err || res.statusCode >= 500) return 'error';
              if (res.statusCode >= 400) return 'warn';
              return 'info';
            },
            autoLogging: {
              ignore: (req) => {
                const url = req.url ?? '';
                return url.startsWith('/api/v1/health');
              },
            },
          },
        };
      },
    }),
  ],
  exports: [PinoLoggerModule],
})
export class LoggerModule {}
