package vqdtask

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

var (
	VqdPollingTaskMap = vqdcms.VqdTaskMap{M: make(map[string]*vqdcms.VQDHandle)}
	TaskFlowMap       *TaskFlow
)

func (c *Core) StartPolling() {
	TaskFlowMap = NewTaskFlow(int(c.Cfg.VqdConfig.PollingNum))
	c.UpdatePollingTask()
	// 注册开始执行回调
	TaskFlowMap.RegisterStartCallback(func(task Task, executeDuration time.Duration, timeout time.Duration) {
		slog.Debug("[全局回调-开始]", "任务", task.ID(), "预期耗时", executeDuration, "超时阈值", timeout)
		// 可扩展：记录任务启动时间、初始化监控指标、打印执行前日志等
		c.AddPollingTaskVqd(task.ID(), task.GetPara(), task.GetHandleInfo())
	})
	TaskFlowMap.RegisterSuccessCallback(func(taskID string, executeDuration time.Duration, elapsed time.Duration) {
		slog.Debug("[全局回调-成功]", "任务", taskID, "预期耗时", executeDuration, "实际耗时", elapsed)
		// 可扩展：记录日志、更新监控指标、发送通知等
		c.DelPollingTaskVqd(taskID)
	})

	// 注册失败回调
	TaskFlowMap.RegisterFailCallback(func(taskID string, err error, elapsed time.Duration) {
		slog.Debug("[全局回调-失败]", "任务", taskID, "原因", err, "实际耗时", elapsed)
		// 可扩展：记录错误日志、触发告警、重试策略等
		c.DelPollingTaskVqd(taskID)
	})

	// 注册超时回调
	TaskFlowMap.RegisterTimeoutCallback(func(taskID string, timeout time.Duration, elapsed time.Duration) {
		slog.Debug("[全局回调-超时]", "任务", taskID, "超时阈值", timeout, "实际耗时", elapsed)
		// 可扩展：发送超时告警、调整任务超时配置等
		c.DelPollingTaskVqd(taskID)
	})
	items, _, err := c.VqdTaskCore.FindVqdPollingAll()
	if err == nil && len(items) > 0 {
		for _, v := range items {
			errs := c.AddPollingTask(v)
			if errs != nil {
				slog.Error("vqd polling add template", "err", errs.Error())
				continue
			}
			time.Sleep(100 * time.Millisecond)
		}
	}
	// 启动任务流
	TaskFlowMap.Start()

}
func (c *Core) StopPolling() {
	if TaskFlowMap != nil {
		// 停止任务流
		TaskFlowMap.Close()
	}
}
func (c *Core) HasRunningTask(chnId string) int {
	pollingId := fmt.Sprintf("%s_polling", chnId)
	if TaskFlowMap.HasRunning(pollingId) {
		return 1
	}
	return 0
}
func (c *Core) AddPollingTask(task *vqd.VqdPolling) error {

	chnId := task.ChannelID
	pollingId := fmt.Sprintf("%s_polling", chnId)
	para := vqdcms.NewVQDPara(TaskFlowMap.TaskTemplate)
	info := vqdcms.VQDHandleInfo{
		ChannelID:    chnId,
		ChannelName:  task.ChannelName,
		TaskID:       task.ID,
		TaskName:     "轮询",
		TemplateID:   TaskFlowMap.TaskTemplate.ID,
		TemplateName: TaskFlowMap.TaskTemplate.Name,
		PlanID:       0,
		PlanName:     "全量",
		Plans:        "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
	}
	newTask := NewPollingTask(pollingId, time.Duration(c.Cfg.VqdConfig.PollingTime)*time.Second, time.Duration(c.Cfg.VqdConfig.PollingTime+1)*time.Second, para, info)
	TaskFlowMap.AddTask(newTask)
	return nil
}

func (c *Core) UpdatePollingTask() {
	cof := c.Cfg.VqdConfig
	TaskFlowMap.BatchSetExecuteDuration(time.Duration(cof.PollingTime) * time.Second)
	TaskFlowMap.BatchSetTimeout(time.Duration(cof.PollingTime+1) * time.Second)
	TaskFlowMap.SetMaxConcurrent(int(cof.PollingNum))

	taskTemplate, err := c.VqdTaskCore.GetIDVqdTaskTemplate(context.TODO(), int64(cof.PollingTemplate))
	if err != nil {
		slog.Error("vqd polling find template", "err", err.Error())
	}
	if taskTemplate != nil {
		TaskFlowMap.SetTemplate(taskTemplate)
	}
}

func (c *Core) DelPollingTask(chnId string) error {
	pollingId := fmt.Sprintf("%s_polling", chnId)
	TaskFlowMap.RemoveTask(pollingId, true)
	c.DelPollingTaskVqd(pollingId)
	return nil
}

func (c *Core) AddPollingTaskVqd(pollingId string, para vqdcms.VQDPara, info vqdcms.VQDHandleInfo) {
	v := vqdcms.NewVQDHandle(c.ResultCb, c.HostCore, info).Create(para, info.Plans)
	VqdPollingTaskMap.StoreChildMap(pollingId, v)
}
func (c *Core) DelPollingTaskVqd(pollingId string) {
	v, ok := VqdPollingTaskMap.LoadTaskMap(pollingId)
	if ok {
		v.Destroy()
	}
	VqdPollingTaskMap.DeleteTaskMap(pollingId)
}

type PollingTask struct {
	id              string
	timeout         time.Duration
	executeDuration time.Duration
	info            vqdcms.VQDHandleInfo
	para            vqdcms.VQDPara
	mu              sync.RWMutex // 任务配置修改锁

}

func NewPollingTask(id string, executeDuration, timeout time.Duration, para vqdcms.VQDPara, info vqdcms.VQDHandleInfo) *PollingTask {
	return &PollingTask{
		id:              id,
		timeout:         timeout,
		executeDuration: executeDuration,
		para:            para,
		info:            info,
	}
}

func (d *PollingTask) ID() string { return d.id }

// Timeout 读取超时时间（读锁保护）
func (d *PollingTask) Timeout() time.Duration {
	d.mu.RLock()
	defer d.mu.RUnlock()
	return d.timeout
}
func (d *PollingTask) GetPara() vqdcms.VQDPara {
	d.mu.RLock()
	defer d.mu.RUnlock()
	return d.para
}
func (d *PollingTask) GetHandleInfo() vqdcms.VQDHandleInfo {
	d.mu.RLock()
	defer d.mu.RUnlock()
	return d.info
}

// ExecuteDuration 读取执行时长（读锁保护）
func (d *PollingTask) ExecuteDuration() time.Duration {
	d.mu.RLock()
	defer d.mu.RUnlock()
	return d.executeDuration
}

// SetTimeout 动态修改超时时间（写锁保护）
func (d *PollingTask) SetTimeout(newTimeout time.Duration) {
	d.mu.Lock()
	oldTimeout := d.timeout
	d.timeout = newTimeout
	d.mu.Unlock()
	slog.Debug("任务超时时间修改", "id", d.id, "old", oldTimeout, "news", newTimeout)
}

// SetExecuteDuration 动态修改执行时长（写锁保护）
func (d *PollingTask) SetExecuteDuration(newDuration time.Duration) {
	d.mu.Lock()
	oldDuration := d.executeDuration
	d.executeDuration = newDuration
	d.mu.Unlock()
	slog.Debug("任务执行时长修改", "id", d.id, "old", oldDuration, "news", newDuration)
}

func (d *PollingTask) Execute(ctx context.Context) error {
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	// 执行时读取最新的执行时长配置
	targetDuration := d.ExecuteDuration()
	elapsed := 0 * time.Millisecond

	for {
		select {
		case <-ctx.Done():
			return fmt.Errorf("任务被取消: %v (预期执行: %v, 已执行: %v)", ctx.Err(), targetDuration, elapsed)
		case <-ticker.C:
			elapsed += 100 * time.Millisecond
			if elapsed >= targetDuration {
				fmt.Println("执行成功:", d.ID())
				return nil
			}
		}
	}
}
