// Aggressive process cleanup utility
import { exec } from 'child_process'
import { promisify } from 'util'

const execAsync = promisify(exec)

class AggressiveCleanup {
  private static instance: AggressiveCleanup
  private cleanupInterval: NodeJS.Timeout | null = null
  private isRunning = false
  private isInitialized = false
  private lastApiCallTime = Date.now()

  private constructor() {
    // Don't auto-start - let startup.ts control it
  }

  static getInstance(): AggressiveCleanup {
    if (!AggressiveCleanup.instance) {
      AggressiveCleanup.instance = new AggressiveCleanup()
    }
    return AggressiveCleanup.instance
  }

  startPeriodicCleanup() {
    if (this.isInitialized) {
      console.log('🔄 Aggressive cleanup already initialized')
      return
    }

    this.isInitialized = true
    console.log('🚀 Starting aggressive cleanup system')

    // In development, use on-demand cleanup instead of periodic
    if (process.env.NODE_ENV === 'development') {
      console.log('🔧 Development mode: Using on-demand cleanup (triggered after analysis)')
      console.log('✅ On-demand cleanup system ready')
      return
    }

    // Production: Clean up every 10 minutes (longer intervals)
    this.cleanupInterval = setInterval(async () => {
      try {
        await this.cleanupOrphanedProcesses()
      } catch (error) {
        console.error('Error in periodic cleanup:', error)
      }
    }, 10 * 60 * 1000) // 10 minutes

    // Also run initial cleanup after 60 seconds
    setTimeout(() => {
      this.cleanupOrphanedProcesses().catch(console.error)
    }, 60000)

    console.log('✅ Periodic cleanup system started (10 min intervals)')
  }

  async cleanupOrphanedProcesses(): Promise<void> {
    if (this.isRunning) return
    
    this.isRunning = true
    const isDevelopment = process.env.NODE_ENV === 'development'
    const cleanupType = isDevelopment ? 'gentle' : 'aggressive'
    
    console.log(`🧹 Running ${cleanupType} cleanup for orphaned processes...`)

    try {
      // Multiple checks for active analysis sessions
      let hasActiveSessions = false
      
      // Check 1: Progress tracker
      try {
        const { progressTracker } = await import('./progress-tracker')
        const activeSessions = progressTracker.getActiveSessions()
        
        if (activeSessions.length > 0) {
          console.log(`⚠️  Found ${activeSessions.length} active progress sessions: ${activeSessions.join(', ')}`)
          hasActiveSessions = true
        }
      } catch (importError) {
        console.log('⚠️  Could not check progress tracker, being conservative')
        hasActiveSessions = true // Be conservative if we can't check
      }

      // Check 2: Recent browser activity (processes less than 2 minutes old)
      const chromiumProcesses = await this.findChromiumProcesses()
      if (chromiumProcesses.length > 0) {
        const recentProcesses = await this.checkProcessAge(chromiumProcesses)
        if (recentProcesses.length > 0) {
          console.log(`⚠️  Found ${recentProcesses.length} recent browser processes (< 2 min old)`)
          hasActiveSessions = true
        }
      }

      // Check 3: In development, be extra conservative - only cleanup if no recent API calls
      if (isDevelopment) {
        const lastApiCall = this.getLastApiCallTime()
        const timeSinceLastApi = Date.now() - lastApiCall
        if (timeSinceLastApi < 30000) { // 30 seconds
          console.log(`⚠️  Recent API activity detected (${Math.round(timeSinceLastApi/1000)}s ago), skipping cleanup`)
          hasActiveSessions = true
        }
      }

      if (hasActiveSessions) {
        console.log(`⚠️  Skipping cleanup - active analysis detected`)
        return
      }
      
      console.log('✅ No active analysis sessions detected, proceeding with cleanup')

      // Find and kill orphaned chromium processes
      if (chromiumProcesses.length > 0) {
        console.log(`Found ${chromiumProcesses.length} chromium processes, cleaning up...`)
        
        for (const pid of chromiumProcesses) {
          try {
            if (isDevelopment) {
              // In development, use gentler SIGTERM first
              console.log(`🔧 Dev mode: Gentle shutdown of process ${pid}`)
              await execAsync(`kill -TERM ${pid}`)
              // Give process 5 seconds to shut down gracefully (increased from 3)
              await new Promise(resolve => setTimeout(resolve, 5000))
              
              // Check if process is still running
              try {
                await execAsync(`kill -0 ${pid}`)
                // Process still running, force kill
                console.log(`⚠️  Process ${pid} didn't shut down gracefully, force killing`)
                await execAsync(`kill -9 ${pid}`)
              } catch {
                // Process already dead, that's good
                console.log(`✅ Process ${pid} shut down gracefully`)
              }
            } else {
              // Production: immediate force kill
              await execAsync(`kill -9 ${pid}`)
              console.log(`✅ Killed process ${pid}`)
            }
          } catch (error) {
            // Process might already be dead
            console.log(`ℹ️  Process ${pid} may already be terminated`)
          }
        }
      } else {
        console.log('✅ No orphaned chromium processes found')
      }

      // Clean up temp directories
      try {
        await execAsync('rm -rf /tmp/puppeteer_dev_chrome_profile-* 2>/dev/null || true')
        console.log('✅ Cleaned up temp directories')
      } catch (error) {
        // Ignore errors
      }

      // Clean up shared memory
      try {
        await execAsync('rm -rf /dev/shm/.org.chromium.* 2>/dev/null || true')
        console.log('✅ Cleaned up shared memory')
      } catch (error) {
        // Ignore errors
      }

    } catch (error) {
      console.error(`Error in ${cleanupType} cleanup:`, error)
    } finally {
      this.isRunning = false
    }
  }

  private async findChromiumProcesses(): Promise<string[]> {
    try {
      const { stdout } = await execAsync('ps aux | grep -E "(chromium|chrome)" | grep -v grep | awk \'{print $2}\'')
      return stdout.trim().split('\n').filter((pid: string) => pid && pid !== '')
    } catch (error) {
      return []
    }
  }

  private async checkProcessAge(pids: string[]): Promise<string[]> {
    const recentProcesses: string[] = []
    const twoMinutesAgo = Date.now() - (2 * 60 * 1000)
    
    for (const pid of pids) {
      try {
        const { stdout } = await execAsync(`ps -o lstart= -p ${pid}`)
        const startTime = new Date(stdout.trim()).getTime()
        if (startTime > twoMinutesAgo) {
          recentProcesses.push(pid)
        }
      } catch (error) {
        // Process might not exist anymore, skip
      }
    }
    
    return recentProcesses
  }

  private getLastApiCallTime(): number {
    return this.lastApiCallTime
  }

  updateApiCallTime(): void {
    this.lastApiCallTime = Date.now()
  }

  async forceCleanup(): Promise<void> {
    console.log('🚨 Force cleanup initiated...')
    
    // Stop periodic cleanup
    if (this.cleanupInterval) {
      clearInterval(this.cleanupInterval)
    }

    // Run aggressive cleanup
    await this.cleanupOrphanedProcesses()
    
    // Kill all chromium processes
    try {
      await execAsync('pkill -9 -f "chromium" 2>/dev/null || true')
      await execAsync('pkill -9 -f "chrome" 2>/dev/null || true')
      console.log('✅ Force killed all browser processes')
    } catch (error) {
      console.error('Error in force cleanup:', error)
    }
  }

  // New method for on-demand cleanup after analysis
  async runPostAnalysisCleanup(): Promise<void> {
    const isDevelopment = process.env.NODE_ENV === 'development'
    
    if (isDevelopment) {
      console.log('🔧 Development mode: Checking if safe to cleanup...')
      
      // In development, still check for completion flags before cleanup
      const isAnalysisComplete = await this.checkAnalysisCompletion()
      if (isAnalysisComplete) {
        console.log('✅ Analysis complete, safe to cleanup Chromium processes')
        await this.cleanupChromeProcessesOnly()
      } else {
        console.log('⏳ Analysis still running, skipping cleanup to prevent interference')
      }
      return
    }
    
    console.log('🧹 Post-analysis cleanup triggered...')
    
    // Small delay to ensure analysis processes are fully closed
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    await this.cleanupOrphanedProcesses()
  }

  private async checkAnalysisCompletion(): Promise<boolean> {
    try {
      // Check if analysis completion flag exists
      const { analysisCompletionFlag } = await import('./analysis-completion-flag')
      return analysisCompletionFlag.canCleanup()
    } catch (error) {
      console.log('⚠️ Could not check analysis completion, assuming it is complete')
      return true // Assume complete if we can't check
    }
  }

  private async cleanupChromeProcessesOnly(): Promise<void> {
    console.log('🧹 Cleaning up Chromium processes only...')
    
    try {
      // First pass - graceful termination
      const gracefulCommands = [
        "pkill -TERM -f 'chromium.*--remote-debugging-port' || true",
        "pkill -TERM -f 'chromium.*--user-data-dir' || true", 
        "pkill -TERM -f '/usr/lib/chromium/chromium' || true",
        "pkill -TERM -f chrome || true"
      ]

      for (const cmd of gracefulCommands) {
        try {
          await execAsync(cmd)
        } catch (error) {
          // Ignore errors - processes might not exist
        }
      }

      // Wait 2 seconds for graceful shutdown
      await new Promise(resolve => setTimeout(resolve, 2000))

      // Second pass - force kill
      const forceCommands = [
        "pkill -9 -f 'chromium.*--remote-debugging-port' || true",
        "pkill -9 -f 'chromium.*--user-data-dir' || true",
        "pkill -9 -f '/usr/lib/chromium/chromium' || true", 
        "pkill -9 -f chrome || true",
        "pkill -9 -f 'type=zygote' || true",
        "pkill -9 -f 'type=gpu-process' || true",
        "pkill -9 -f 'type=utility' || true",
        "pkill -9 -f 'defunct' || true"
      ]

      for (const cmd of forceCommands) {
        try {
          await execAsync(cmd)
        } catch (error) {
          // Ignore errors - processes might not exist
        }
      }

      console.log('✅ Chromium processes cleanup completed')
    } catch (error) {
      console.error('❌ Error in Chromium cleanup:', error)
    }
  }

  // Force cleanup after successful trade execution
  async forceCleanupAfterTrade(): Promise<void> {
    console.log('💰 Trade executed - forcing cleanup of Chromium processes')
    
    // Wait longer to ensure analysis is completely done and no new analysis starts
    await new Promise(resolve => setTimeout(resolve, 10000)) // 10 seconds
    
    // Check if analysis is still running
    const analysisComplete = await this.checkAnalysisCompletion()
    if (analysisComplete) {
      console.log('✅ Analysis confirmed complete, proceeding with cleanup')
      await this.cleanupChromeProcessesOnly()
    } else {
      console.log('⏳ Analysis still active, skipping cleanup to prevent interference')
    }
  }

  stop(): void {
    if (this.cleanupInterval) {
      clearInterval(this.cleanupInterval)
      this.cleanupInterval = null
    }
  }
}

// Initialize the aggressive cleanup
const aggressiveCleanup = AggressiveCleanup.getInstance()

export default aggressiveCleanup
