import { EventEmitter } from 'events';
import { 
  ProjectMethodology, 
  MethodologyStore, 
  MethodologyMigration,
  AGILE_TOOLS,
  KANBAN_TOOLS,
  COMMON_TOOLS
} from './types.js';
import { ConfigManager } from '../../config/config-manager.js';
import { randomUUID } from 'crypto';

export class MethodologyManager extends EventEmitter {
  private store: MethodologyStore;
  private configManager: ConfigManager;

  constructor(configManager?: ConfigManager) {
    super();
    this.configManager = configManager || new ConfigManager();
    this.store = {};
  }

  async init(): Promise<void> {
    await this.loadStore();
  }

  async setMethodology(type: 'agile' | 'kanban', userId: string): Promise<ProjectMethodology> {
    if (this.store.currentMethodology?.lockedAt) {
      throw new Error(`Methodology is locked since ${this.store.currentMethodology.lockedAt}. Cannot change.`);
    }

    const methodology: ProjectMethodology = {
      type,
      allowedTools: [...COMMON_TOOLS, ...(type === 'agile' ? AGILE_TOOLS : KANBAN_TOOLS)],
      disallowedTools: type === 'agile' ? KANBAN_TOOLS : AGILE_TOOLS,
      configuration: this.getDefaultConfig(type),
      migrationHistory: []
    };

    if (this.store.currentMethodology && this.store.currentMethodology.type !== type) {
      // Record migration
      const migration: MethodologyMigration = {
        id: randomUUID(),
        fromType: this.store.currentMethodology.type,
        toType: type,
        migratedAt: new Date(),
        migratedBy: userId,
        itemsMigrated: 0,
        dataLost: this.identifyDataLoss(this.store.currentMethodology.type, type)
      };
      methodology.migrationHistory.push(migration);
    }

    this.store.currentMethodology = methodology;
    await this.saveStore();
    
    this.emit('methodology-changed', methodology);
    
    return methodology;
  }

  async lockMethodology(userId: string): Promise<void> {
    if (!this.store.currentMethodology) {
      throw new Error('No methodology set to lock');
    }

    if (this.store.currentMethodology.lockedAt) {
      throw new Error('Methodology is already locked');
    }

    this.store.currentMethodology.lockedAt = new Date();
    this.store.currentMethodology.lockedBy = userId;
    
    await this.saveStore();
    this.emit('methodology-locked', this.store.currentMethodology);
  }

  isToolAllowed(toolName: string): boolean {
    if (!this.store.currentMethodology) {
      return true; // No methodology set, allow all
    }

    return this.store.currentMethodology.allowedTools.includes(toolName);
  }

  getCurrentMethodology(): ProjectMethodology | undefined {
    return this.store.currentMethodology;
  }

  async warnAboutConflict(toolName: string): Promise<boolean> {
    const now = new Date();
    const lastWarning = this.store.lastWarningShown;
    
    // Only show warning once per hour
    if (lastWarning && (now.getTime() - lastWarning.getTime()) < 3600000) {
      return false;
    }

    this.store.lastWarningShown = now;
    await this.saveStore();
    
    this.emit('methodology-conflict-warning', {
      toolName,
      currentMethodology: this.store.currentMethodology?.type,
      message: `Tool '${toolName}' belongs to a different methodology. Consider switching methodologies or using the appropriate tools.`
    });
    
    return true;
  }

  private getDefaultConfig(type: 'agile' | 'kanban'): any {
    if (type === 'agile') {
      return {
        sprintDuration: 14,
        velocityTracking: true,
        storyPointScale: [1, 2, 3, 5, 8, 13, 21],
        retrospectiveFrequency: 'end_of_sprint',
        customColumns: ['To Do', 'In Progress', 'Review', 'Testing', 'Done'],
        defaultPriorities: ['low', 'medium', 'high', 'critical'],
        requiredFields: ['title', 'description', 'storyPoints', 'acceptanceCriteria']
      };
    } else {
      return {
        wip_limits: {
          'To Do': 0,
          'In Progress': 3,
          'Review': 2,
          'Done': 0
        },
        cycleTimeTracking: true,
        leadTimeTracking: true,
        customColumns: ['Backlog', 'To Do', 'In Progress', 'Review', 'Done'],
        defaultPriorities: ['low', 'medium', 'high', 'urgent'],
        requiredFields: ['title', 'description']
      };
    }
  }

  private identifyDataLoss(from: string, to: string): string[] {
    const dataLoss: string[] = [];
    
    if (from === 'agile' && to === 'kanban') {
      dataLoss.push(
        'Sprint information will be lost',
        'Story points will not be used in Kanban',
        'Velocity tracking will be disabled',
        'Epic relationships may need adjustment'
      );
    } else if (from === 'kanban' && to === 'agile') {
      dataLoss.push(
        'WIP limits will be removed',
        'Cycle time tracking will be converted to velocity',
        'Tasks will need story point estimation',
        'Tasks will need to be assigned to sprints'
      );
    }
    
    return dataLoss;
  }

  async suggestMigrationPath(from: string, to: string): Promise<string[]> {
    const suggestions: string[] = [];
    
    if (from === 'agile' && to === 'kanban') {
      suggestions.push(
        '1. Complete or cancel active sprints',
        '2. Convert stories to tasks',
        '3. Set up WIP limits for columns',
        '4. Archive velocity reports',
        '5. Train team on Kanban metrics'
      );
    } else if (from === 'kanban' && to === 'agile') {
      suggestions.push(
        '1. Group related tasks into stories',
        '2. Estimate story points for all items',
        '3. Create initial sprint backlog',
        '4. Define sprint cadence',
        '5. Set up velocity tracking'
      );
    }
    
    return suggestions;
  }

  private async loadStore(): Promise<void> {
    const storageManager = this.configManager.getStorageManager();
    const data = await storageManager.loadData('methodology-config', 'methodology.json');
    if (data) {
      this.store = data;
    }
  }

  private async saveStore(): Promise<void> {
    const storageManager = this.configManager.getStorageManager();
    await storageManager.saveData('methodology-config', 'methodology.json', this.store);
  }
}