/**
 * Copyright (c) 2024-2026 Тарабанов Александр Викторович
 * All rights reserved.
 * 
 * This software is proprietary and confidential.
 * Unauthorized copying, modification, or distribution is prohibited.
 * 
 * For licensing inquiries: info@hb3-accelerator.com
 * Website: https://hb3-accelerator.com
 * GitHub: https://github.com/VC-HB3-Accelerator
 */

const crypto = require('crypto');
const EventEmitter = require('events');

class DeploymentTracker extends EventEmitter {
  constructor() {
    super();
    this.deployments = new Map(); // В продакшене использовать Redis
    this.logger = require('../utils/logger');
  }
  
  // Создать новый деплой
  createDeployment(params, deploymentId = null) {
    const id = deploymentId || this.generateDeploymentId();
    
    const deployment = {
      id: id,
      status: 'pending',
      stage: 'initializing',
      progress: 0,
      startedAt: new Date(),
      updatedAt: new Date(),
      params,
      networks: {},
      logs: [],
      result: null,
      error: null
    };
    
    this.deployments.set(id, deployment);
    this.logger.info(`📝 Создан новый деплой: ${id}`);
    console.log(`[DEPLOYMENT_TRACKER] Создан деплой: ${id}, всего деплоев: ${this.deployments.size}`);
    
    return id;
  }
  
  // Получить статус деплоя
  getDeployment(deploymentId) {
    return this.deployments.get(deploymentId);
  }
  
  // Обновить статус деплоя
  updateDeployment(deploymentId, updates) {
    const deployment = this.deployments.get(deploymentId);
    if (!deployment) {
      this.logger.error(`❌ Деплой не найден: ${deploymentId}`);
      return false;
    }
    
    Object.assign(deployment, updates, { updatedAt: new Date() });
    this.deployments.set(deploymentId, deployment);
    
    // Отправляем событие через WebSocket
    this.emit('deployment_updated', {
      deploymentId,
      ...updates
    });
    
    return true;
  }
  
  // Добавить лог
  addLog(deploymentId, message, type = 'info') {
    const deployment = this.deployments.get(deploymentId);
    if (!deployment) return false;
    
    const logEntry = {
      id: Date.now() + Math.random(), // Уникальный ID для отслеживания дублирования
      timestamp: new Date(),
      message,
      type
    };
    
    deployment.logs.push(logEntry);
    deployment.updatedAt = new Date();
    
    // Логируем отправку лога для отладки дублирования (только в debug режиме)
    if (process.env.DEBUG_DEPLOYMENT_LOGS) {
      console.log(`[DEPLOYMENT_TRACKER] Отправляем лог ID=${logEntry.id}: ${message.substring(0, 50)}...`);
    }
    
    // Отправляем только лог через WebSocket (без дублирования)
    this.emit('deployment_updated', {
      deploymentId,
      type: 'deployment_log',
      log: logEntry
    });
    
    return true;
  }
  
  // Обновить статус сети
  updateNetworkStatus(deploymentId, network, status, address = null, message = null) {
    const deployment = this.deployments.get(deploymentId);
    if (!deployment) return false;
    
    deployment.networks[network] = {
      status,
      address,
      message,
      updatedAt: new Date()
    };
    
    deployment.updatedAt = new Date();
    
    // Отправляем обновление через WebSocket
    this.emit('deployment_updated', {
      deploymentId,
      type: 'deployment_network_update',
      network,
      status,
      address,
      message
    });
    
    return true;
  }
  
  // Обновить прогресс
  updateProgress(deploymentId, stage, progress, message = null) {
    const updates = {
      stage,
      progress,
      status: progress >= 100 ? 'completed' : 'in_progress'
    };
    
    // Обновляем без отправки события (только внутреннее обновление)
    const deployment = this.deployments.get(deploymentId);
    if (deployment) {
      Object.assign(deployment, updates, { updatedAt: new Date() });
      this.deployments.set(deploymentId, deployment);
    }
    
    // Лог добавляется через updateDeployment, не дублируем событие
  }
  
  // Завершить деплой успешно
  completeDeployment(deploymentId, result) {
    const updates = {
      status: 'completed',
      progress: 100,
      result,
      completedAt: new Date()
    };
    
    this.updateDeployment(deploymentId, updates);
    
    // Событие уже отправлено через updateDeployment
    
    this.logger.info(`✅ Деплой завершен: ${deploymentId}`);
  }
  
  // Завершить деплой с ошибкой
  failDeployment(deploymentId, error) {
    const updates = {
      status: 'failed',
      error: error.message || error,
      failedAt: new Date()
    };
    
    this.updateDeployment(deploymentId, updates);
    
    // Событие уже отправлено через updateDeployment
    
    this.logger.error(`❌ Деплой провален: ${deploymentId}`, error);
  }
  
  // Очистить старые деплои (вызывать по крону)
  cleanupOldDeployments(olderThanHours = 24) {
    const cutoff = new Date(Date.now() - olderThanHours * 60 * 60 * 1000);
    let cleaned = 0;
    
    for (const [id, deployment] of this.deployments.entries()) {
      if (deployment.updatedAt < cutoff && ['completed', 'failed'].includes(deployment.status)) {
        this.deployments.delete(id);
        cleaned++;
      }
    }
    
    if (cleaned > 0) {
      this.logger.info(`🧹 Очищено ${cleaned} старых деплоев`);
    }
  }
  
  // Сгенерировать уникальный ID
  generateDeploymentId() {
    return `deploy_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`;
  }
  
  // Получить все активные деплои
  getActiveDeployments() {
    const active = [];
    for (const deployment of this.deployments.values()) {
      if (['pending', 'in_progress'].includes(deployment.status)) {
        active.push(deployment);
      }
    }
    return active;
  }
  
  // Получить статистику
  getStats() {
    const stats = {
      total: this.deployments.size,
      pending: 0,
      inProgress: 0,
      completed: 0,
      failed: 0
    };
    
    for (const deployment of this.deployments.values()) {
      switch (deployment.status) {
        case 'pending':
          stats.pending++;
          break;
        case 'in_progress':
          stats.inProgress++;
          break;
        case 'completed':
          stats.completed++;
          break;
        case 'failed':
          stats.failed++;
          break;
      }
    }
    
    return stats;
  }
}

// Singleton экземпляр
const deploymentTracker = new DeploymentTracker();

module.exports = deploymentTracker;
