/**
 * Global Task Manager
 *
 * Tracks background tasks across page navigation and shows notifications on completion.
 */

import { api } from './api'
import { notificationManager } from './notificationManager'

interface TaskInfo {
  taskId: string
  presetId: number
  presetName: string
  startedAt: number
}

interface TaskResult {
  results_count?: number
  new_count?: number
  match_count?: number
  error?: string
}

interface TaskResponse {
  success: boolean
  task: {
    status: string
    result?: TaskResult
  }
}

class TaskManager {
  private runningTasks: Map<string, TaskInfo> = new Map()
  private pollingIntervals: Map<string, ReturnType<typeof setInterval>> = new Map()
  private listeners: Set<(tasks: Map<string, TaskInfo>) => void> = new Set()

  /**
   * Start tracking a background task
   */
  trackTask(taskId: string, presetId: number, presetName: string): void {
    const taskInfo: TaskInfo = {
      taskId,
      presetId,
      presetName,
      startedAt: Date.now()
    }

    this.runningTasks.set(taskId, taskInfo)
    this.notifyListeners()
    this.startPolling(taskId)
  }

  /**
   * Check if a preset is currently running
   */
  isPresetRunning(presetId: number): boolean {
    for (const task of this.runningTasks.values()) {
      if (task.presetId === presetId) {
        return true
      }
    }
    return false
  }

  /**
   * Get all running preset IDs
   */
  getRunningPresetIds(): Set<number> {
    const ids = new Set<number>()
    for (const task of this.runningTasks.values()) {
      ids.add(task.presetId)
    }
    return ids
  }

  /**
   * Subscribe to task updates
   */
  subscribe(listener: (tasks: Map<string, TaskInfo>) => void): () => void {
    this.listeners.add(listener)
    return () => this.listeners.delete(listener)
  }

  private notifyListeners(): void {
    for (const listener of this.listeners) {
      listener(this.runningTasks)
    }
  }

  private startPolling(taskId: string): void {
    const maxDuration = 10 * 60 * 1000 // 10 minutes max
    const pollInterval = 1000 // 1 second

    const poll = async () => {
      const taskInfo = this.runningTasks.get(taskId)
      if (!taskInfo) {
        this.stopPolling(taskId)
        return
      }

      // Check if we've exceeded max duration
      if (Date.now() - taskInfo.startedAt > maxDuration) {
        this.runningTasks.delete(taskId)
        this.stopPolling(taskId)
        this.notifyListeners()
        notificationManager.warning('Timeout', `${taskInfo.presetName}: Task timed out`)
        return
      }

      try {
        const response = await api.get<TaskResponse>(`/celebrity/tasks/${taskId}`)

        if (response.task.status === 'completed') {
          this.runningTasks.delete(taskId)
          this.stopPolling(taskId)
          this.notifyListeners()

          const result = response.task.result
          if (result?.results_count !== undefined || result?.new_count !== undefined) {
            const resultsText = result.results_count ? `${result.results_count} found` : ''
            const matchText = result.match_count ? `${result.match_count} matched` : ''
            const newText = result.new_count !== undefined ? `${result.new_count} new` : ''
            const parts = [resultsText, matchText, newText].filter(Boolean).join(', ')
            notificationManager.success('Complete', `${taskInfo.presetName}: ${parts || 'Discovery complete'}`)
          } else {
            notificationManager.success('Complete', `${taskInfo.presetName}: Discovery complete`)
          }
        } else if (response.task.status === 'failed') {
          this.runningTasks.delete(taskId)
          this.stopPolling(taskId)
          this.notifyListeners()

          notificationManager.error('Failed', response.task.result?.error || `${taskInfo.presetName}: Discovery failed`)
        }
        // Still running - continue polling
      } catch (e) {
        // API error - continue polling (task might not be ready yet)
        console.debug('Task polling error (will retry):', taskId, e)
      }
    }

    // Start polling
    const interval = setInterval(poll, pollInterval)
    this.pollingIntervals.set(taskId, interval)

    // Initial poll after a short delay
    setTimeout(poll, 500)
  }

  private stopPolling(taskId: string): void {
    const interval = this.pollingIntervals.get(taskId)
    if (interval) {
      clearInterval(interval)
      this.pollingIntervals.delete(taskId)
    }
  }
}

// Singleton instance
export const taskManager = new TaskManager()
