package vqdtask

import (
	"context"
	"easyvqd/internal/core/vqd"
	"easyvqd/pkg/vqdcms"
	"fmt"
	"log/slog"
	"sync"
	"time"
)

// TaskSuccessCallback 任务执行成功的全局回调
// 参数：taskID=任务ID, executeDuration=预期执行时长, elapsed=实际耗时
type TaskSuccessCallback func(taskID string, executeDuration time.Duration, elapsed time.Duration)

// TaskFailCallback 任务执行失败的全局回调
// 参数：taskID=任务ID, err=失败原因, elapsed=实际耗时
type TaskFailCallback func(taskID string, err error, elapsed time.Duration)

// TaskTimeoutCallback 任务执行超时的全局回调
// 参数：taskID=任务ID, timeout=超时时间, elapsed=实际耗时
type TaskTimeoutCallback func(taskID string, timeout time.Duration, elapsed time.Duration)

// TaskStartCallback 任务开始执行的全局回调
// 参数：taskID=任务ID, executeDuration=预期执行时长, timeout=超时时间
type TaskStartCallback func(task Task, executeDuration time.Duration, timeout time.Duration)

// Task 任务接口（新增动态配置方法）
type Task interface {
	ID() string
	Execute(ctx context.Context) error
	// 读取配置（带锁）
	Timeout() time.Duration
	GetHandleInfo() vqdcms.VQDHandleInfo
	GetPara() vqdcms.VQDPara
	ExecuteDuration() time.Duration
	// 动态修改配置
	SetTimeout(d time.Duration)
	SetExecuteDuration(d time.Duration)
}

// TaskFlow 任务流管理器（支持动态修改并发数）
type TaskFlow struct {
	runningTasks  map[string]Task      // 正在运行的任务
	waitingTasks  []Task               // 等待执行的任务
	maxConcurrent int                  // 最大并发数（可动态修改）
	TaskTemplate  *vqd.VqdTaskTemplate // 关联模板
	mu            sync.RWMutex         // 并发安全锁
	wg            sync.WaitGroup       // 等待所有goroutine结束
	ctx           context.Context      // 全局上下文
	cancel        context.CancelFunc   // 全局取消函数
	removedTasks  map[string]bool      // 已标记删除的任务ID
	rmMutex       sync.RWMutex         // 删除标记的锁
	closed        bool                 // 标记是否已完全关闭
	concurrentMu  sync.RWMutex         // 并发数修改专用锁
	// ------------------- 回调相关字段 -------------------
	callbackMu      sync.RWMutex        // 回调操作专用锁
	startCallback   TaskStartCallback   // 开始执行回调
	successCallback TaskSuccessCallback // 成功回调
	failCallback    TaskFailCallback    // 失败回调
	timeoutCallback TaskTimeoutCallback // 超时回调
}

// NewTaskFlow 创建任务流实例
func NewTaskFlow(maxConcurrent int) *TaskFlow {
	ctx, cancel := context.WithCancel(context.Background())
	return &TaskFlow{
		runningTasks:  make(map[string]Task),
		waitingTasks:  make([]Task, 0),
		maxConcurrent: maxConcurrent,
		ctx:           ctx,
		cancel:        cancel,
		removedTasks:  make(map[string]bool),
		closed:        false,
	}
}
func (tf *TaskFlow) SetTemplate(Temp *vqd.VqdTaskTemplate) {
	// 加锁修改
	tf.concurrentMu.Lock()
	tf.TaskTemplate = Temp
	tf.concurrentMu.Unlock()
}

// SetMaxConcurrent 动态修改最大并发数
// 返回值：true=修改成功，false=任务流已关闭
func (tf *TaskFlow) SetMaxConcurrent(newConcurrent int) bool {
	// 检查是否已关闭
	tf.mu.RLock()
	closed := tf.closed
	tf.mu.RUnlock()
	if closed {
		slog.Error("任务流已关闭，拒绝修改并发数")
		return false
	}

	if newConcurrent <= 0 {
		slog.Error("并发数必须大于0，修改失败")
		return false
	}

	// 加锁修改
	tf.concurrentMu.Lock()
	oldConcurrent := tf.maxConcurrent
	tf.maxConcurrent = newConcurrent
	tf.concurrentMu.Unlock()

	slog.Debug("最大并发数已修改为", "old", oldConcurrent, "news", newConcurrent)
	return true
}

// AddTask 添加任务到等待队列（锁安全）
func (tf *TaskFlow) AddTask(task Task) {
	// 检查是否已关闭
	tf.mu.RLock()
	closed := tf.closed
	tf.mu.RUnlock()
	if closed {
		slog.Error("任务流已关闭，拒绝添加任务", "id", task.ID())
		return
	}

	// 检查是否被标记删除
	tf.rmMutex.RLock()
	isRemoved := tf.removedTasks[task.ID()]
	tf.rmMutex.RUnlock()
	if isRemoved {
		slog.Error("任务已被标记删除，跳过添加", "id", task.ID())
		return
	}

	// 加写锁，确保并发安全
	tf.mu.Lock()
	defer tf.mu.Unlock()

	// 二次检查关闭状态
	if tf.closed {
		slog.Error("任务流已关闭，拒绝添加任务", "id", task.ID())
		return
	}

	// 避免重复添加
	for _, t := range tf.waitingTasks {
		if t.ID() == task.ID() {
			return
		}
	}
	if _, exists := tf.runningTasks[task.ID()]; exists {
		return
	}

	tf.waitingTasks = append(tf.waitingTasks, task)
	slog.Debug(fmt.Sprintf("任务 %s 已加入等待队列（执行时长: %v, 超时时间: %v）\n", task.ID(), task.ExecuteDuration(), task.Timeout()))
}

// RemoveTask 删除指定ID的任务（锁安全）
func (tf *TaskFlow) RemoveTask(taskID string, immediate bool) bool {
	// 检查是否已关闭
	tf.mu.RLock()
	closed := tf.closed
	tf.mu.RUnlock()
	if closed {
		slog.Error("任务流已关闭，拒绝删除任务", "id", taskID)
		return false
	}

	// 标记任务为删除
	tf.rmMutex.Lock()
	tf.removedTasks[taskID] = true
	tf.rmMutex.Unlock()

	// 加写锁处理任务队列
	tf.mu.Lock()
	defer tf.mu.Unlock()

	removed := false

	// 1. 移除等待队列中的任务
	newWaiting := make([]Task, 0, len(tf.waitingTasks))
	for _, task := range tf.waitingTasks {
		if task.ID() == taskID {
			removed = true
			slog.Debug("从等待队列中删除任务", "id", task.ID())
			continue
		}
		newWaiting = append(newWaiting, task)
	}
	tf.waitingTasks = newWaiting

	// 2. 处理运行中的任务
	if _, exists := tf.runningTasks[taskID]; exists {
		removed = true
		if immediate {
			delete(tf.runningTasks, taskID)
			slog.Debug("标记任务为删除，立即终止当前执行", "id", taskID)
		} else {
			slog.Debug("标记任务为删除，执行完当前周期后移除", "id", taskID)
		}
	}

	// 清理无效标记
	if !removed {
		slog.Debug("任务不存在，删除失败", "id", taskID)
		tf.rmMutex.Lock()
		delete(tf.removedTasks, taskID)
		tf.rmMutex.Unlock()
	}

	return removed
}

// CleanupRemovedTasks 清理已删除任务的残留标记和资源
func (tf *TaskFlow) CleanupRemovedTasks() int {
	// 检查是否已关闭
	tf.mu.RLock()
	closed := tf.closed
	tf.mu.RUnlock()
	if closed {
		slog.Error("任务流已关闭，拒绝执行清理操作")
		return 0
	}

	// 步骤1：收集有效任务ID（读锁）
	tf.mu.RLock()
	validTaskIDs := make(map[string]bool)
	for taskID := range tf.runningTasks {
		validTaskIDs[taskID] = true
	}
	for _, task := range tf.waitingTasks {
		validTaskIDs[task.ID()] = true
	}
	tf.mu.RUnlock()

	// 步骤2：清理无效删除标记
	tf.rmMutex.Lock()
	cleanedCount := 0
	for taskID := range tf.removedTasks {
		if !validTaskIDs[taskID] {
			delete(tf.removedTasks, taskID)
			cleanedCount++
			slog.Debug("清理无效删除标记", "id", taskID)
		}
	}
	tf.rmMutex.Unlock()

	// 步骤3：清理等待队列残留
	tf.mu.Lock()
	newWaiting := make([]Task, 0, len(tf.waitingTasks))
	for _, task := range tf.waitingTasks {
		tf.rmMutex.RLock()
		isRemoved := tf.removedTasks[task.ID()]
		tf.rmMutex.RUnlock()
		if !isRemoved {
			newWaiting = append(newWaiting, task)
		} else {
			slog.Debug("清理等待队列中已删除的任务", "id", task.ID())
			cleanedCount++
		}
	}
	tf.waitingTasks = newWaiting
	tf.mu.Unlock()

	slog.Debug("清理完成，共清理无效标记/残留任务", "count", cleanedCount)
	return cleanedCount
}

// Start 启动任务流
func (tf *TaskFlow) Start() {
	tf.mu.RLock()
	closed := tf.closed
	tf.mu.RUnlock()
	if closed {
		slog.Error("任务流已关闭，无法启动")
		return
	}

	go tf.scheduleLoop()
	slog.Info("任务流已启动")
}

// Close 完全释放整个任务流
func (tf *TaskFlow) Close() {
	tf.mu.Lock()
	defer tf.mu.Unlock()

	if tf.closed {
		slog.Error("任务流已处于关闭状态，无需重复关闭")
		return
	}

	// 标记为已关闭
	tf.closed = true
	slog.Info("开始完全释放任务流资源...")

	// 取消全局上下文
	tf.cancel()

	// 等待所有goroutine退出（临时解锁避免死锁）
	tf.mu.Unlock()
	tf.wg.Wait()
	tf.mu.Lock()

	// 清空所有队列
	tf.waitingTasks = nil
	tf.runningTasks = nil

	// 清空删除标记
	tf.rmMutex.Lock()
	tf.removedTasks = nil
	tf.rmMutex.Unlock()

	slog.Info("任务流已完全关闭，所有资源已释放")
}

// Reset 重置任务流
func (tf *TaskFlow) Reset(maxConcurrent int) {
	tf.Close()

	tf.mu.Lock()
	defer tf.mu.Unlock()

	// 重建上下文
	ctx, cancel := context.WithCancel(context.Background())
	tf.ctx = ctx
	tf.cancel = cancel

	// 重建队列
	tf.waitingTasks = make([]Task, 0)
	tf.runningTasks = make(map[string]Task)
	tf.removedTasks = make(map[string]bool)

	// 重置状态
	tf.closed = false
	tf.maxConcurrent = maxConcurrent

	slog.Debug("任务流已重置，最大并发数", "count", maxConcurrent)
}

// scheduleLoop 任务调度主循环
func (tf *TaskFlow) scheduleLoop() {
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-tf.ctx.Done():
			slog.Info("任务调度循环已停止")
			return
		case <-ticker.C:
			// 检查是否已关闭
			tf.mu.RLock()
			closed := tf.closed
			tf.mu.RUnlock()
			if closed {
				return
			}
			tf.scheduleTasks()
		}
	}
}

// scheduleTasks 调度任务执行（动态读取并发数）
func (tf *TaskFlow) scheduleTasks() {
	// 读取当前运行数和最新并发数
	tf.mu.RLock()
	currentRunning := len(tf.runningTasks)
	tf.mu.RUnlock()

	tf.concurrentMu.RLock()
	maxConcurrent := tf.maxConcurrent
	tf.concurrentMu.RUnlock()

	availableSlots := maxConcurrent - currentRunning

	// 检查是否已关闭
	tf.mu.RLock()
	closed := tf.closed
	tf.mu.RUnlock()

	if closed || availableSlots <= 0 {
		return
	}

	// 取出待执行任务
	tf.mu.Lock()
	tasksToRun := make([]Task, 0)
	if len(tf.waitingTasks) > 0 {
		take := availableSlots
		if take > len(tf.waitingTasks) {
			take = len(tf.waitingTasks)
		}
		tasksToRun = tf.waitingTasks[:take]
		tf.waitingTasks = tf.waitingTasks[take:]
	}
	tf.mu.Unlock()

	// 执行任务
	for _, task := range tasksToRun {
		tf.runTask(task)
	}
}

// runTask 执行单个任务（使用最新的任务配置）
func (tf *TaskFlow) runTask(task Task) {
	taskID := task.ID()

	// 加写锁标记为运行中
	tf.mu.Lock()
	// 检查状态
	if tf.closed {
		tf.mu.Unlock()
		slog.Error("任务流已关闭，取消执行任务", "id", taskID)
		return
	}
	tf.rmMutex.RLock()
	isRemoved := tf.removedTasks[taskID]
	tf.rmMutex.RUnlock()
	if isRemoved {
		tf.mu.Unlock()
		slog.Debug("任务已被删除，取消执行", "id", taskID)
		return
	}
	// 标记为运行中
	tf.runningTasks[taskID] = task
	tf.mu.Unlock()

	// 执行任务协程
	tf.wg.Add(1)
	go func(t Task) {
		defer tf.wg.Done()

		// 获取任务最新的超时配置（执行时读取，保证使用最新值）
		timeout := t.Timeout()
		executeDuration := t.ExecuteDuration()

		// 创建超时上下文（使用最新超时时间）
		taskCtx, taskCancel := context.WithTimeout(tf.ctx, timeout)
		defer taskCancel()
		tf.callbackMu.RLock()
		defer tf.callbackMu.RUnlock()
		if tf.startCallback != nil {
			tf.startCallback(t, executeDuration, timeout)
		}
		slog.Debug(fmt.Sprintf("开始执行任务: %s (执行时长: %v, 超时时间: %v)", t.ID(), executeDuration, timeout))
		startTime := time.Now()

		// 执行任务
		err := t.Execute(taskCtx)
		elapsed := time.Since(startTime)

		// 清理运行标记
		tf.mu.Lock()
		delete(tf.runningTasks, t.ID())
		tf.mu.Unlock()

		// 检查状态
		tf.rmMutex.RLock()
		isRemoved = tf.removedTasks[t.ID()]
		tf.rmMutex.RUnlock()
		tf.mu.RLock()
		closed := tf.closed
		tf.mu.RUnlock()

		// 处理执行结果
		if err != nil {
			tf.callbackMu.RLock()
			defer tf.callbackMu.RUnlock()
			// 区分超时和普通失败
			if ctxErr := taskCtx.Err(); ctxErr == context.DeadlineExceeded {
				// 超时触发超时回调
				if tf.timeoutCallback != nil {
					tf.timeoutCallback(t.ID(), timeout, elapsed)
				}
			} else {
				// 普通失败触发失败回调
				if tf.failCallback != nil {
					tf.failCallback(t.ID(), err, elapsed)
				}
			}
			slog.Debug(fmt.Sprintf("任务 %s 执行失败: %v (耗时: %v)", t.ID(), err, elapsed))
			if !closed && !isRemoved {
				tf.AddTask(t)
			} else {
				slog.Debug("任务已被删除/任务流关闭，失败后不重试", "id", t.ID())
			}
		} else {
			tf.callbackMu.RLock()
			defer tf.callbackMu.RUnlock()
			if tf.successCallback != nil {
				tf.successCallback(t.ID(), executeDuration, elapsed)
			}
			slog.Debug(fmt.Sprintf("任务 %s 执行成功 (预期执行时长: %v, 实际耗时: %v)", t.ID(), executeDuration, elapsed))
			if !closed && !isRemoved {
				tf.AddTask(t)
			} else {
				slog.Debug("任务已被删除/任务流关闭，成功后不再循环", "id", t.ID())
				tf.rmMutex.Lock()
				delete(tf.removedTasks, t.ID())
				tf.rmMutex.Unlock()
			}
		}
	}(task)
}

// BatchSetTimeout 批量给【所有任务】设置 超时时间
func (tf *TaskFlow) BatchSetTimeout(timeout time.Duration) {
	tf.mu.RLock()
	defer tf.mu.RUnlock()

	if tf.closed {
		slog.Error("任务流已关闭，批量设置超时失败")
		return
	}

	// 设置等待队列所有任务
	for _, task := range tf.waitingTasks {
		task.SetTimeout(timeout)
	}
	// 设置运行中任务
	for _, task := range tf.runningTasks {
		task.SetTimeout(timeout)
	}
	slog.Debug("所有任务超时时间已批量设置为", "time", timeout)
}

// BatchSetExecuteDuration 批量给【所有任务】设置 执行时长
func (tf *TaskFlow) BatchSetExecuteDuration(duration time.Duration) {
	tf.mu.RLock()
	defer tf.mu.RUnlock()

	if tf.closed {
		slog.Error("任务流已关闭，批量设置执行时长失败")
		return
	}

	// 设置等待队列
	for _, task := range tf.waitingTasks {
		task.SetExecuteDuration(duration)
	}
	// 设置运行中任务
	for _, task := range tf.runningTasks {
		task.SetExecuteDuration(duration)
	}
	slog.Debug("所有任务执行时长已批量设置为", "duration", duration)
}

// BatchSetByIDs 按任务ID列表批量设置 超时+执行时长
func (tf *TaskFlow) BatchSetByIDs(ids []string, timeout, duration time.Duration) {
	tf.mu.RLock()
	defer tf.mu.RUnlock()

	if tf.closed {
		slog.Error("任务流已关闭，按ID批量设置失败")
		return
	}

	idSet := make(map[string]bool)
	for _, id := range ids {
		idSet[id] = true
	}

	// 处理等待队列
	for _, task := range tf.waitingTasks {
		if idSet[task.ID()] {
			task.SetTimeout(timeout)
			task.SetExecuteDuration(duration)
		}
	}
	// 处理运行中队列
	for _, task := range tf.runningTasks {
		if idSet[task.ID()] {
			task.SetTimeout(timeout)
			task.SetExecuteDuration(duration)
		}
	}
	tf.UnregisterAllCallbacks()
	slog.Debug("所有任务执行按ID批量设置完成", "超时", timeout, "执行时长", duration)
}

// 判断是否在执行
func (tf *TaskFlow) HasRunning(taskId string) bool {
	tf.mu.RLock()
	defer tf.mu.RUnlock()
	if tf.closed {
		slog.Error("任务流已关闭")
		return false
	}
	flag := false
	// 处理运行中队列
	for _, task := range tf.runningTasks {
		if task.ID() == taskId {
			flag = true
			break
		}
	}
	return flag
}

// RegisterSuccessCallback 注册任务成功的全局回调
func (tf *TaskFlow) RegisterSuccessCallback(callback TaskSuccessCallback) {
	tf.callbackMu.Lock()
	defer tf.callbackMu.Unlock()
	tf.successCallback = callback
	slog.Debug("任务成功全局回调已注册")
}

// RegisterFailCallback 注册任务失败的全局回调
func (tf *TaskFlow) RegisterFailCallback(callback TaskFailCallback) {
	tf.callbackMu.Lock()
	defer tf.callbackMu.Unlock()
	tf.failCallback = callback
	slog.Debug("任务失败全局回调已注册")
}

// RegisterTimeoutCallback 注册任务超时的全局回调
func (tf *TaskFlow) RegisterTimeoutCallback(callback TaskTimeoutCallback) {
	tf.callbackMu.Lock()
	defer tf.callbackMu.Unlock()
	tf.timeoutCallback = callback
	slog.Debug("任务超时全局回调已注册")
}

// RegisterStartCallback 注册任务开始执行的全局回调
func (tf *TaskFlow) RegisterStartCallback(callback TaskStartCallback) {
	tf.callbackMu.Lock()
	defer tf.callbackMu.Unlock()
	tf.startCallback = callback
	slog.Debug("任务开始执行全局回调已注册")
}

// UnregisterAllCallbacks 注销所有全局回调
func (tf *TaskFlow) UnregisterAllCallbacks() {
	tf.callbackMu.Lock()
	defer tf.callbackMu.Unlock()
	tf.successCallback = nil
	tf.failCallback = nil
	tf.timeoutCallback = nil
	tf.startCallback = nil
	slog.Info("所有全局回调已注销")
}
