import chalk from 'chalk';

interface ProgressState {
  total: number;
  completed: number;
  failed: number;
  running: number;
  startTime: number;
}

export class ProgressTracker {
  private state: ProgressState;
  private updateInterval?: NodeJS.Timer;
  private lastUpdate: number = 0;

  constructor(total: number) {
    this.state = {
      total,
      completed: 0,
      failed: 0,
      running: 0,
      startTime: Date.now(),
    };
  }

  start() {
    this.updateInterval = setInterval(() => {
      this.render();
    }, 500);
  }

  stop() {
    if (this.updateInterval) {
      clearInterval(this.updateInterval);
      this.updateInterval = undefined;
    }
  }

  update(status: { completed: number; failed: number; running: number }) {
    this.state.completed = status.completed;
    this.state.failed = status.failed;
    this.state.running = status.running;
    this.lastUpdate = Date.now();
  }

  private getProgressBar(percentage: number, width: number = 30): string {
    const filled = Math.round((percentage / 100) * width);
    const empty = width - filled;
    
    const filledBar = '█'.repeat(filled);
    const emptyBar = '░'.repeat(empty);
    
    return chalk.green(filledBar) + chalk.gray(emptyBar);
  }

  private formatTime(ms: number): string {
    const seconds = Math.floor(ms / 1000);
    const minutes = Math.floor(seconds / 60);
    
    if (minutes > 0) {
      return `${minutes}m ${seconds % 60}s`;
    }
    return `${seconds}s`;
  }

  private estimateTimeRemaining(): string {
    const elapsed = Date.now() - this.state.startTime;
    const progress = this.state.completed / this.state.total;
    
    if (progress === 0) return 'calculating...';
    
    const estimated = elapsed / progress;
    const remaining = estimated - elapsed;
    
    return remaining > 0 ? this.formatTime(remaining) : '0s';
  }

  private render() {
    const { completed, failed, running, total } = this.state;
    const pending = total - completed - failed - running;
    const completionPercentage = ((completed + failed) / total) * 100;
    
    // Clear the line and render progress
    process.stdout.write('\r\x1b[K');
    
    const progressBar = this.getProgressBar(completionPercentage);
    const elapsed = this.formatTime(Date.now() - this.state.startTime);
    const estimated = this.estimateTimeRemaining();
    
    const statusLine = [
      `${progressBar} ${completionPercentage.toFixed(1)}%`,
      chalk.green(`✅ ${completed}`),
      running > 0 ? chalk.yellow(`🔄 ${running}`) : '',
      failed > 0 ? chalk.red(`❌ ${failed}`) : '',
      pending > 0 ? chalk.gray(`⏳ ${pending}`) : '',
      `⏱️  ${elapsed}`,
      completionPercentage < 100 ? `(~${estimated} left)` : '',
    ].filter(Boolean).join(' ');
    
    process.stdout.write(statusLine);
  }

  complete() {
    this.stop();
    const elapsed = this.formatTime(Date.now() - this.state.startTime);
    
    process.stdout.write('\r\x1b[K');
    
    if (this.state.failed > 0) {
      console.log(`🎯 Orchestration completed with ${this.state.failed} failures in ${elapsed}`);
    } else {
      console.log(`🎉 Orchestration completed successfully in ${elapsed}`);
    }
  }

  error(message: string) {
    this.stop();
    const elapsed = this.formatTime(Date.now() - this.state.startTime);
    
    process.stdout.write('\r\x1b[K');
    console.log(`💥 Orchestration failed after ${elapsed}: ${message}`);
  }
}
