import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';

export interface Config {
  port: number;
  nodeEnv: string;
  redisUrl: string;
  pansouUrl: string;
  pansouAuthToken: string;
  videoParserUrl: string;
  jwtSecret: string;
  adminUsername: string;
  adminPassword: string;
  validation: {
    concurrency: number;
    timeout: number;
    cacheTtlValid: number;
    cacheTtlInvalid: number;
  };
  corsOrigin: string;
  cookieEncryptionKey: string;
  logLevel: string;
  appVersionFile: string;
  uploadDir: string;
  chromiumPath: string;
  dbPath: string;
}

const DEFAULT_JWT_SECRETS = ['', 'cloudsearch-jwt-secret-dev', 'cloudsearch-jwt-secret-2024', 'your-super-secret-jwt-key-change-me'];
const DEFAULT_PASSWORDS = ['', 'admin123', 'admin', 'password', '123456', '0nL5kLhMIJ1121PYmQb25A'];

function loadOrGenerateSecret(key: string, envKey: string, defaultVal: string, isDefault: (v: string) => boolean, byteLen: number): string {
  const envVal = process.env[envKey];

  // If env var is set and NOT a known default → use it directly
  if (envVal && !isDefault(envVal)) {
    return envVal;
  }

  // Try to load from persisted secrets file
  const secretsPath = path.join(process.env.DATA_DIR || '/app/data', 'secrets.json');
  try {
    if (fs.existsSync(secretsPath)) {
      const secrets = JSON.parse(fs.readFileSync(secretsPath, 'utf8'));
      if (secrets[key]) return secrets[key];
    }
  } catch (_) {}

  // If env var is set but it's a default → still use it (admin set it explicitly, maybe for dev)
  if (envVal) return envVal;

  // No env var, no persisted file → auto-generate
  const generated = byteLen === 16
    ? crypto.randomBytes(8).toString('hex')       // 16-char hex for passwords
    : crypto.randomBytes(byteLen).toString('hex'); // 64-char hex for JWT

  try {
    const dir = path.dirname(secretsPath);
    if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
    let existing: Record<string, string> = {};
    if (fs.existsSync(secretsPath)) {
      try { existing = JSON.parse(fs.readFileSync(secretsPath, 'utf8')); } catch (_) {}
    }
    existing[key] = generated;
    fs.writeFileSync(secretsPath, JSON.stringify(existing, null, 2));
    console.log(`[Config] Auto-generated ${envKey} → saved to secrets.json`);
  } catch (e: any) {
    console.log(`[Config] Could not persist ${envKey}:`, e.message);
  }
  return generated;
}

const config: Config = {
  port: parseInt(process.env.PORT || '9527', 10),
  nodeEnv: process.env.NODE_ENV || 'development',
  redisUrl: process.env.REDIS_URL || 'redis://localhost:6379',
  pansouUrl: process.env.PANSOU_URL || 'http://localhost:8888',
  pansouAuthToken: process.env.PANSOU_AUTH_TOKEN || '',
  videoParserUrl: process.env.VIDEO_PARSER_URL || 'http://localhost:3001',
  jwtSecret: loadOrGenerateSecret('jwt_secret', 'JWT_SECRET', 'cloudsearch-jwt-secret-dev', (v) => DEFAULT_JWT_SECRETS.includes(v), 32),
  adminUsername: process.env.ADMIN_USERNAME || 'admin',
  adminPassword: loadOrGenerateSecret('admin_password', 'ADMIN_PASSWORD', 'admin123', (v) => DEFAULT_PASSWORDS.includes(v), 16),
  validation: {
    concurrency: parseInt(process.env.VALIDATION_CONCURRENCY || '10', 10),
    timeout: parseInt(process.env.VALIDATION_TIMEOUT || '5000', 10),
    cacheTtlValid: parseInt(process.env.CACHE_TTL_VALID || '14400', 10),    // 4小时
    cacheTtlInvalid: parseInt(process.env.CACHE_TTL_INVALID || '3600', 10),  // 1小时
  },
  corsOrigin: process.env.CORS_ORIGIN || '',
  cookieEncryptionKey: process.env.COOKIE_ENCRYPTION_KEY || '',
  logLevel: process.env.LOG_LEVEL || (process.env.NODE_ENV === 'production' ? 'info' : 'debug'),
  appVersionFile: process.env.APP_VERSION_FILE || '/app/VERSION',
  uploadDir: process.env.UPLOAD_DIR || '/app/uploads',
  chromiumPath: process.env.CHROMIUM_PATH || "/usr/bin/chromium-browser",
  dbPath: process.env.DB_PATH || './data/cloudsearch.db',
};

// Startup validation done by startup-validator
export default config;
