#!/usr/bin/env bun
/* eslint-disable no-console */
import { join } from 'path';
import { parseArgs } from 'util';
import { redactSecrets } from './utils/secrets';
import {
  checkRequiredEnvVars,
  formatValidationResult,
  validateCompleteness,
  validateConfig,
} from './utils/validation';
import { ConfigManager } from './config-manager';
import { baseAppSchema } from './schemas';
import type { Environment } from './types';

interface CliOptions {
  config?: string;
  env?: string;
  validate?: boolean;
  show?: boolean;
  check?: boolean;
  json?: boolean;
  help?: boolean;
}

const REQUIRED_PATHS = [
  'service.name',
  'service.port',
  'database.postgres.host',
  'database.postgres.database',
];

const REQUIRED_ENV_VARS = ['NODE_ENV'];

const SECRET_PATHS = [
  'database.postgres.password',
  'database.mongodb.uri',
  'providers.quoteMedia.apiKey',
  'providers.interactiveBrokers.clientId',
];

function printUsage() {
  console.log(`
Stock Bot Configuration CLI

Usage: bun run config-cli [options]

Options:
  --config <path>   Path to config directory (default: ./config)
  --env <env>       Environment to use (development, test, production)
  --validate        Validate configuration against schema
  --show            Show current configuration (secrets redacted)
  --check           Run all configuration checks
  --json            Output in JSON format
  --help            Show this help message

Examples:
  # Validate configuration
  bun run config-cli --validate

  # Show configuration for production
  bun run config-cli --env production --show

  # Run all checks
  bun run config-cli --check

  # Output configuration as JSON
  bun run config-cli --show --json
`);
}

async function main() {
  const { values } = parseArgs({
    args: process.argv.slice(2),
    options: {
      config: { type: 'string' },
      env: { type: 'string' },
      validate: { type: 'boolean' },
      show: { type: 'boolean' },
      check: { type: 'boolean' },
      json: { type: 'boolean' },
      help: { type: 'boolean' },
    },
  }) as { values: CliOptions };

  if (values.help) {
    printUsage();
    process.exit(0);
  }

  const configPath = values.config || join(process.cwd(), 'config');
  const environment = values.env as Environment;

  try {
    const manager = new ConfigManager({
      configPath,
      environment,
    });

    const config = await manager.initialize(baseAppSchema);

    if (values.validate) {
      const result = validateConfig(config, baseAppSchema);

      if (values.json) {
        console.log(JSON.stringify(result, null, 2));
      } else {
        console.log(formatValidationResult(result));
      }

      process.exit(result.valid ? 0 : 1);
    }

    if (values.show) {
      const redacted = redactSecrets(config, SECRET_PATHS);

      if (values.json) {
        console.log(JSON.stringify(redacted, null, 2));
      } else {
        console.log('Current Configuration:');
        console.log(JSON.stringify(redacted, null, 2));
      }
    }

    if (values.check) {
      console.log('Running configuration checks...\n');

      // Schema validation
      console.log('1. Schema Validation:');
      const schemaResult = validateConfig(config, baseAppSchema);
      console.log(formatValidationResult(schemaResult));
      console.log();

      // Environment variables
      console.log('2. Required Environment Variables:');
      const envResult = checkRequiredEnvVars(REQUIRED_ENV_VARS);
      console.log(formatValidationResult(envResult));
      console.log();

      // Required paths
      console.log('3. Required Configuration Paths:');
      const pathResult = validateCompleteness(config, REQUIRED_PATHS);
      console.log(formatValidationResult(pathResult));
      console.log();

      // Overall result
      const allValid = schemaResult.valid && envResult.valid && pathResult.valid;

      if (allValid) {
        console.log('✅ All configuration checks passed!');
        process.exit(0);
      } else {
        console.log('❌ Some configuration checks failed');
        process.exit(1);
      }
    }

    if (!values.validate && !values.show && !values.check) {
      console.log('No action specified. Use --help for usage information.');
      process.exit(1);
    }
  } catch (error) {
    if (values.json) {
      console.error(JSON.stringify({ error: String(error) }));
    } else {
      console.error('Error:', error);
    }
    process.exit(1);
  }
}

// Run CLI
if (import.meta.main) {
  main();
}
