/**
 * World Events System Manager
 * Handles event spawning, lifecycle, and completion
 */

export class EventManager {
  store: any;
  activeTimers: Map<string, any>;
  
  constructor(gameStore: any) {
    this.store = gameStore;
    this.activeTimers = new Map();
  }

  /**
   * Check if an event can spawn
   * @param {Object} event - Event definition
   * @returns {boolean} - Can spawn
   */
  canSpawnEvent(event) {
    const { player, world } = this.store.getState();
    const { spawnConditions } = event;

    // Check if already active or completed
    if (world.activeEvents.some(e => e.id === event.id)) {
      return false;
    }
    if (world.completedEvents.includes(event.id)) {
      return false;
    }

    // Check time period
    if (spawnConditions.timePeriod && world.currentEra !== spawnConditions.timePeriod) {
      return false;
    }

    // Check player level
    if (spawnConditions.playerLevel && player.level < spawnConditions.playerLevel) {
      return false;
    }

    // Check location if specified
    if (spawnConditions.location && world.currentLocation !== spawnConditions.location) {
      return false;
    }

    // Check random chance
    if (spawnConditions.randomChance) {
      return Math.random() < spawnConditions.randomChance;
    }

    return true;
  }

  /**
   * Spawn an event
   * @param {Object} event - Event definition
   * @returns {boolean} - Success
   */
  spawnEvent(event) {
    if (!this.canSpawnEvent(event)) {
      return false;
    }

    const activeEvent = {
      ...event,
      startTime: Date.now(),
      expiresAt: Date.now() + event.duration,
      progress: {
        objectives: event.objectives.map(obj => ({
          ...obj,
          current: 0,
          completed: false
        })),
        percentComplete: 0
      }
    };

    this.store.getState().addActiveEvent(activeEvent);

    // Set expiration timer
    const timer = setTimeout(() => {
      this.expireEvent(event.id);
    }, event.duration);

    this.activeTimers.set(event.id, timer);

    return true;
  }

  /**
   * Update event progress
   * @param {string} eventId - Event identifier
   * @param {number} objectiveIndex - Objective index
   * @param {number} progress - Progress amount to add
   */
  updateEventProgress(eventId, objectiveIndex, progress = 1) {
    const { world } = this.store.getState();
    const event = world.activeEvents.find(e => e.id === eventId);

    if (!event) return;

    const objective = event.progress.objectives[objectiveIndex];
    if (!objective || objective.completed) return;

    objective.current = Math.min(objective.current + progress, objective.count);
    
    if (objective.current >= objective.count) {
      objective.completed = true;
    }

    // Calculate overall progress
    const totalObjectives = event.progress.objectives.length;
    const completedObjectives = event.progress.objectives.filter(o => o.completed).length;
    event.progress.percentComplete = (completedObjectives / totalObjectives) * 100;

    // Check if all objectives completed
    if (completedObjectives === totalObjectives) {
      this.completeEvent(eventId);
    }
  }

  /**
   * Complete an event
   * @param {string} eventId - Event identifier
   */
  completeEvent(eventId) {
    const { world } = this.store.getState();
    const event = world.activeEvents.find(e => e.id === eventId);

    if (!event) return;

    // Award rewards
    if (event.rewards) {
      const { addFans, addCredits } = this.store.getState();
      
      if (event.rewards.fans) addFans(event.rewards.fans);
      if (event.rewards.credits) addCredits(event.rewards.credits);
      
      // Handle unlocks (new musicians, locations, etc.)
      if (event.rewards.unlocks) {
        // Process unlocks (to be implemented with unlock system)
      }
    }

    // Clear timer
    const timer = this.activeTimers.get(eventId);
    if (timer) {
      clearTimeout(timer);
      this.activeTimers.delete(eventId);
    }

    // Mark as completed
    this.store.getState().completeEvent(eventId);
  }

  /**
   * Expire an event (time ran out)
   * @param {string} eventId - Event identifier
   */
  expireEvent(eventId) {
    const timer = this.activeTimers.get(eventId);
    if (timer) {
      clearTimeout(timer);
      this.activeTimers.delete(eventId);
    }

    this.store.getState().removeActiveEvent(eventId);
  }

  /**
   * Get active events
   * @returns {Array} - Active events
   */
  getActiveEvents() {
    return this.store.getState().world.activeEvents;
  }

  /**
   * Get time remaining for an event
   * @param {string} eventId - Event identifier
   * @returns {number} - Milliseconds remaining
   */
  getTimeRemaining(eventId) {
    const { world } = this.store.getState();
    const event = world.activeEvents.find(e => e.id === eventId);

    if (!event) return 0;

    const remaining = event.expiresAt - Date.now();
    return Math.max(0, remaining);
  }

  /**
   * Clean up all event timers (call on unmount)
   */
  cleanup() {
    this.activeTimers.forEach(timer => clearTimeout(timer));
    this.activeTimers.clear();
  }
}

