// src/services/logger.server.ts
/**
 * SERVER-SIDE LOGGER
 * This file configures and exports a singleton `pino` logger instance for
 * server-side use, adhering to ADR-004 for structured JSON logging.
 *
 * In production/test environments, logs are written to:
 * - stdout (for PM2 capture and real-time viewing)
 * - File: logs/app.log (for Logstash aggregation)
 *
 * Log files are stored in the application's logs/ directory:
 * - Production: /var/www/flyer-crawler.projectium.com/logs/
 * - Test: /var/www/flyer-crawler-test.projectium.com/logs/
 * - Dev container: /app/logs/
 */
import pino from 'pino';
import fs from 'fs';
import path from 'path';

const isProduction = process.env.NODE_ENV === 'production';
const isTest = process.env.NODE_ENV === 'test';
const isStaging = process.env.NODE_ENV === 'staging';
const isDevelopment = !isProduction && !isTest && !isStaging;

// Determine log directory based on environment
// In production/test, use the application directory's logs folder
// In development, use process.cwd()/logs
const getLogDirectory = (): string => {
  // Allow override via environment variable
  if (process.env.LOG_DIR) {
    return process.env.LOG_DIR;
  }

  // Default to logs/ in current working directory
  return path.join(process.cwd(), 'logs');
};

// Ensure log directory exists (only in production/test where we write files)
const ensureLogDirectory = (): string | null => {
  if (isDevelopment) {
    return null; // Don't create log files in development
  }

  const logDir = getLogDirectory();
  try {
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true });
    }
    return logDir;
  } catch (error) {
    // If we can't create the directory, fall back to stdout only
    console.error(`Failed to create log directory ${logDir}:`, error);
    return null;
  }
};

// Common redaction configuration
const redactConfig = {
  paths: [
    'req.headers.authorization',
    'req.headers.cookie',
    '*.body.password',
    '*.body.newPassword',
    '*.body.currentPassword',
    '*.body.confirmPassword',
    '*.body.refreshToken',
    '*.body.token',
  ],
  censor: '[REDACTED]',
};

// Create the logger based on environment
const createLogger = (): pino.Logger => {
  const logDir = ensureLogDirectory();

  // Development: Use pino-pretty for human-readable output
  if (isDevelopment) {
    return pino({
      level: 'debug',
      transport: {
        target: 'pino-pretty',
        options: {
          colorize: true,
          translateTime: 'SYS:standard',
          ignore: 'pid,hostname',
        },
      },
      redact: redactConfig,
    });
  }

  // Production/Test: Write to both stdout and file
  if (logDir) {
    const logFilePath = path.join(logDir, 'app.log');

    // Create a multi-stream destination
    const streams: pino.StreamEntry[] = [
      // Stream to stdout (for PM2 and real-time viewing)
      { stream: process.stdout },
      // Stream to file (for Logstash aggregation)
      {
        stream: pino.destination({
          dest: logFilePath,
          sync: false, // Async for better performance
          mkdir: true, // Create directory if needed
        }),
      },
    ];

    return pino(
      {
        level: isProduction ? 'info' : 'debug',
        redact: redactConfig,
      },
      pino.multistream(streams),
    );
  }

  // Fallback: stdout only (if log directory creation failed)
  return pino({
    level: isProduction ? 'info' : 'debug',
    redact: redactConfig,
  });
};

export const logger = createLogger();

const debugModules = (process.env.DEBUG_MODULES || '').split(',').map((s) => s.trim());

export const createScopedLogger = (moduleName: string) => {
  // If DEBUG_MODULES contains "ai-service" or "*", force level to 'debug'
  const isDebugEnabled = debugModules.includes('*') || debugModules.includes(moduleName);

  return logger.child({
    module: moduleName,
    level: isDebugEnabled ? 'debug' : logger.level,
  });
};
