#!/usr/bin/env node

import fs from 'fs'
import path from 'path'
import { execSync } from 'child_process'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const sslDir = path.join(__dirname, 'ssl')
const keyPath = path.join(sslDir, 'server.key')
const certPath = path.join(sslDir, 'server.crt')

const colors = {
  reset: '\x1b[0m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m'
}

const log = (message, color = 'reset') => {
  console.log(`${colors[color]}${message}${colors.reset}`)
}

const checkOpenSSL = () => {
  try {
    execSync('openssl version', { stdio: 'pipe' })
    return true
  } catch (error) {
    return false
  }
}

const installInstructions = () => {
  log('\n📋 Инструкции по установке OpenSSL:', 'cyan')
  log('Windows: https://slproweb.com/products/Win32OpenSSL.html', 'blue')
  log('macOS: brew install openssl', 'blue')
  log('Ubuntu/Debian: sudo apt-get install openssl', 'blue')
  log('CentOS/RHEL: sudo yum install openssl', 'blue')
}

const createCertificates = (domain = 'localhost', days = 365) => {
  if (!fs.existsSync(sslDir)) {
    fs.mkdirSync(sslDir, { recursive: true })
    log(`📁 Создана папка: ${sslDir}`, 'green')
  }

  try {
    log('🔐 Создание SSL сертификатов...', 'yellow')
    
    // Генерируем приватный ключ
    log('📝 Генерация приватного ключа...', 'blue')
    execSync(`openssl genrsa -out "${keyPath}" 2048`, { stdio: 'pipe' })
    
    // Конфигурация для сертификата с SAN
    const configContent = `
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
C = RU
ST = Development
L = Local
O = Development Server
OU = IT Department
CN = ${domain}

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = ${domain}
DNS.2 = *.${domain}
DNS.3 = localhost
DNS.4 = *.localhost
IP.1 = 127.0.0.1
IP.2 = ::1
`
    
    const configPath = path.join(sslDir, 'openssl.conf')
    fs.writeFileSync(configPath, configContent.trim())
    
    // Генерируем сертификат
    log('📜 Генерация сертификата...', 'blue')
    const certCommand = `openssl req -new -x509 -key "${keyPath}" -out "${certPath}" -days ${days} -config "${configPath}" -extensions v3_req`
    execSync(certCommand, { stdio: 'pipe' })
    
    // Удаляем временный конфиг
    fs.unlinkSync(configPath)
    
    log('\n✅ SSL сертификаты успешно созданы!', 'green')
    log(`🔑 Ключ: ${keyPath}`, 'cyan')
    log(`📄 Сертификат: ${certPath}`, 'cyan')
    log(`🌐 Домен: ${domain}`, 'cyan')
    log(`⏰ Действителен: ${days} дней`, 'cyan')
    
    // Показываем информацию о сертификате
    showCertInfo()
    
    log('\n⚠️  Важно:', 'yellow')
    log('• Это сертификаты только для разработки', 'yellow')
    log('• Добавьте сертификат в доверенные в браузере для устранения предупреждений', 'yellow')
    
  } catch (error) {
    log('\n❌ Ошибка создания SSL сертификатов:', 'red')
    log(error.message, 'red')
    installInstructions()
  }
}

const showCertInfo = () => {
  if (!fs.existsSync(certPath)) {
    log('❌ Сертификат не найден', 'red')
    return
  }
  
  try {
    log('\n📋 Информация о сертификате:', 'cyan')
    const certInfo = execSync(`openssl x509 -in "${certPath}" -text -noout`, { encoding: 'utf8' })
    
    // Извлекаем нужную информацию
    const subjectMatch = certInfo.match(/Subject: (.+)/);
    const validFromMatch = certInfo.match(/Not Before: (.+)/);
    const validToMatch = certInfo.match(/Not After : (.+)/);
    const sanMatch = certInfo.match(/DNS:([^,\n]+)/g);
    
    if (subjectMatch) log(`📝 Subject: ${subjectMatch[1].trim()}`, 'blue')
    if (validFromMatch) log(`📅 Действителен с: ${validFromMatch[1].trim()}`, 'blue')
    if (validToMatch) log(`📅 Действителен до: ${validToMatch[1].trim()}`, 'blue')
    if (sanMatch) {
      log(`🌐 Домены: ${sanMatch.map(d => d.replace('DNS:', '')).join(', ')}`, 'blue')
    }
    
  } catch (error) {
    log('❌ Ошибка чтения информации о сертификате', 'red')
  }
}

const deleteCertificates = () => {
  let deleted = false
  
  if (fs.existsSync(keyPath)) {
    fs.unlinkSync(keyPath)
    log(`🗑️  Удален ключ: ${keyPath}`, 'yellow')
    deleted = true
  }
  
  if (fs.existsSync(certPath)) {
    fs.unlinkSync(certPath)
    log(`🗑️  Удален сертификат: ${certPath}`, 'yellow')
    deleted = true
  }
  
  if (deleted) {
    log('✅ SSL сертификаты удалены', 'green')
  } else {
    log('ℹ️  SSL сертификаты не найдены', 'blue')
  }
}

const checkCertificates = () => {
  const keyExists = fs.existsSync(keyPath)
  const certExists = fs.existsSync(certPath)
  
  log('\n🔍 Проверка SSL сертификатов:', 'cyan')
  log(`🔑 Ключ: ${keyExists ? '✅ Существует' : '❌ Не найден'}`, keyExists ? 'green' : 'red')
  log(`📄 Сертификат: ${certExists ? '✅ Существует' : '❌ Не найден'}`, certExists ? 'green' : 'red')
  
  if (keyExists && certExists) {
    showCertInfo()
  }
  
  return keyExists && certExists
}

const showHelp = () => {
  log('\n🔧 SSL Manager - Утилита для управления SSL сертификатами\n', 'cyan')
  log('Использование:', 'yellow')
  log('  node ssl-manager.js <команда> [опции]\n', 'blue')
  log('Команды:', 'yellow')
  log('  create [domain] [days]  Создать новые сертификаты (по умолчанию: localhost, 365 дней)', 'blue')
  log('  check                   Проверить существующие сертификаты', 'blue')
  log('  info                    Показать информацию о сертификате', 'blue')
  log('  delete                  Удалить существующие сертификаты', 'blue')
  log('  help                    Показать эту справку\n', 'blue')
  log('Примеры:', 'yellow')
  log('  node ssl-manager.js create', 'green')
  log('  node ssl-manager.js create mysite.local 30', 'green')
  log('  node ssl-manager.js check', 'green')
}

// Основная логика
const command = process.argv[2]
const arg1 = process.argv[3]
const arg2 = process.argv[4]

// Проверяем наличие OpenSSL
if (!checkOpenSSL() && command !== 'help' && command !== 'check') {
  log('❌ OpenSSL не найден в системе', 'red')
  installInstructions()
  process.exit(1)
}

switch (command) {
  case 'create':
    const domain = arg1 || 'localhost'
    const days = parseInt(arg2) || 365
    createCertificates(domain, days)
    break
    
  case 'check':
    checkCertificates()
    break
    
  case 'info':
    showCertInfo()
    break
    
  case 'delete':
    deleteCertificates()
    break
    
  case 'help':
  case undefined:
    showHelp()
    break
    
  default:
    log(`❌ Неизвестная команда: ${command}`, 'red')
    showHelp()
    process.exit(1)
}