import type { ParallelTaskExecuteContext, ParallelTaskItem } from '../types'
import { getUuid } from '@minto-ai/tools'
import { BaseHandler } from '../core'
import { ParallelHandlerStatus, ParallelTaskItemStatus } from '../types'

/**
 * 并行任务处理器 - 并行处理队列中的任务
 *
 * 特点：
 * - 支持并行执行任务
 * - 支持任务执行前的自定义条件检查
 * - 实现完整的生命周期管理（激活、待机、执行、成功、销毁）
 * - 可与其他处理器组成处理链
 *
 * 使用场景：
 * - 需要并行执行的任务处理
 * - 资源充足且任务独立的场景
 */
abstract class ParallelFactory<O, R> extends BaseHandler<O, R> {
  /**
   * 获取待处理任务数量
   */
  protected taskQueue: Array<ParallelTaskItem<O>> = []

  /**
   * 当前处理器状态
   */
  public handlerStatus: ParallelHandlerStatus = ParallelHandlerStatus.OFFLINE

  /**
   * 待处理任务队列
   */
  public get taskQueueLength(): number {
    return this.taskQueue.length
  }

  constructor() {
    super()
  }

  /**
   * 检查任务执行条件
   * 子类可重写此方法，实现自定义的任务执行前置条件检查
   *
   * @returns {boolean} - 当满足执行条件时返回 true，否则返回 false
   */
  public executePreCheck(): boolean {
    return true
  }

  /**
   * 触发处理器激活行为（空闲状态 => 激活状态）
   */
  public triggerHandlerActive(): void {
    this.setHandlerStatus(ParallelHandlerStatus.ACTIVE)
    this.onActive()
    this.triggerHandlerPending()
  }

  /**
   *  触发处理器待机行为（激活状态 => 待执行状态）
   */
  public triggerHandlerPending(): void {
    this.setHandlerStatus(ParallelHandlerStatus.PENDING)
  }

  /**
   * 触发处理器执行行为（激活状态 => 执行状态）
   */
  public async triggerHandlerExecute(): Promise<void> {
    this.setHandlerStatus(ParallelHandlerStatus.EXECUTING)

    Promise.resolve().then(() => {
      this.taskQueue
        .filter(({ status }) => status === ParallelTaskItemStatus.PENDING)
        .forEach((taskItem) => {
          taskItem.status = ParallelTaskItemStatus.EXECUTING

          const isFirstExecute = this.isFirstExecute
          if (isFirstExecute) {
            this.isFirstExecute = false
            this.onBeforeFirstExecute()
          }

          let isLastExecute = false

          if (
            this.isHandleDataAcceptedComplete
            && this.taskQueue.every(({ status }) => status !== ParallelTaskItemStatus.PENDING)
          ) {
            isLastExecute = true
          }

          const context = {
            taskItem,
            isFirstExecute,
            isLastExecute,
          } as ParallelTaskExecuteContext<O, R>

          this.execute(context)
        })
    })
  }

  public handle(original: O): void {
    this.taskQueue.push({
      uuid: getUuid(),
      original,
      status: ParallelTaskItemStatus.PENDING,
    })

    if (!this.executePreCheck()) {
      this.setHandlerStatus(ParallelHandlerStatus.PENDING)
      return
    }

    this.triggerHandlerExecute()
  }

  /**
   * 处理队列
   */
  public taskCompletedCallback(uuid: string): void {
    const taskIndex = this.taskQueue.findIndex(item => item.uuid === uuid)
    if (taskIndex !== -1) {
      this.taskQueue[taskIndex].status = ParallelTaskItemStatus.COMPLETED
      this.taskQueue.splice(taskIndex, 1)
    }

    if (this.isHandleDataAcceptedComplete && this.taskQueue.length === 0) {
      this.triggerHandlerCompleted()
      if (this.isLastHandler) {
        this.triggerAppFinish()
      }
    }
  }

  /**
   * 触发处理器成功行为（执行状态 => 成功状态）
   */
  public triggerHandlerCompleted(): void {
    this.setHandlerStatus(ParallelHandlerStatus.COMPLETED)
    if (this.nextHandler) {
      this.nextHandler.handle(null)
      this.nextHandler.isHandleDataAcceptedComplete = true
    }
    this.onCompleted()
  }

  /**
   * 触发处理器销毁行为（待机状态 => 销毁状态）
   */
  public triggerHandlerFinish(): void {
    this.taskQueue = []
    this.isFirstExecute = true
    this.isHandleDataAcceptedComplete = false
    this.setHandlerStatus(ParallelHandlerStatus.FINISH)
    this.onFinish()
  }

  /**
   * 触发应用被销毁行为
   */
  public triggerAppFinish(): void {
    this.executeController?.$bus.emit('_appFinish')
  }
}

export default ParallelFactory
