package timer

import (
	"goutil/logUtilPlus"
	"time"
)

// 触发类型
const (
	// TriggerTypeMinute 一分钟
	TriggerTypeMinute = iota + 1
	// TriggerTypeFiveMinute 五分钟
	TriggerTypeFiveMinute
	// TriggerTypeTenMinute 十分钟
	TriggerTypeTenMinute
	// TriggerTypeHalfHour 半小时
	TriggerTypeHalfHour
	// TriggerTypeHour 一小时
	TriggerTypeHour
	// TriggerTypeEightHour 八小时
	TriggerTypeEightHour
	// TriggerTypeDay 一天 每天0点触发
	TriggerTypeDay
	// TriggerTypeWeek 一周 （周日0点触发）
	TriggerTypeWeek
	// TriggerTypeMonth 每月1号0点触发
	TriggerTypeMonth
)

// TimerHandlerFunc 定义可执行的函数类型
type timerHandlerFunc func(nowTime time.Time) error

// 时间触发管理
var (
	timerHandlerMap = make(map[int][]timerHandlerFunc)
	timerTypeMap    = map[int]struct{}{
		TriggerTypeMinute:     {},
		TriggerTypeFiveMinute: {},
		TriggerTypeTenMinute:  {},
		TriggerTypeHalfHour:   {},
		TriggerTypeHour:       {},
		TriggerTypeEightHour:  {},
		TriggerTypeDay:        {},
		TriggerTypeWeek:       {},
		TriggerTypeMonth:      {},
	}
)

// Register 注册时间触发器
// @param timerType 时间触发类型
// @param timerFunc 时间触发函数
func Register(timerType int, timerFunc timerHandlerFunc) {

	// 检查timerType是否在常量中
	if _, ok := timerTypeMap[timerType]; !ok {
		logUtilPlus.ErrorLog("注册时间触发器失败，类型不存在", "timerType", timerType)
		return
	}

	if _, ok := timerHandlerMap[timerType]; !ok {
		timerHandlerMap[timerType] = make([]timerHandlerFunc, 0)
	}
	timerHandlerMap[timerType] = append(timerHandlerMap[timerType], timerFunc)
}

// Execute 执行时间触发器
// @param timerType 时间触发类型
// @param nowTime 当前时间
func Execute(timerType int, nowTime time.Time) {
	if _, ok := timerHandlerMap[timerType]; !ok {
		return
	}
	for _, timerHandlerFunc := range timerHandlerMap[timerType] {
		if err := timerHandlerFunc(nowTime); err != nil {
			logUtilPlus.ErrorLog("执行时间触发器失败", "timerType", timerType, "err", err)
		}
	}
}

// 初始化init
func init() {
	go timerHandler()
}

// 定时触发函数
func timerHandler() {

	// 每一分钟执行一次
	ticker := time.NewTicker(time.Minute)
	defer ticker.Stop()
	defer func() {
		if err := recover(); err != nil {
			logUtilPlus.ErrorLog("定时触发函数异常", "err", err)
			restartTimerHandler()
		}
	}()
	for {
		select {
		case nowTime := <-ticker.C:
			go func() {
				// 触发minute
				Execute(TriggerTypeMinute, nowTime)
				// 触发fiveMinute
				if nowTime.Minute()%5 == 0 {
					Execute(TriggerTypeFiveMinute, nowTime)
				}
				// 触发tenMinute
				if nowTime.Minute()%10 == 0 {
					Execute(TriggerTypeTenMinute, nowTime)
				}
				// 触发halfHour
				if nowTime.Minute()%30 == 0 {
					Execute(TriggerTypeHalfHour, nowTime)
				}
				// 触发hour
				if nowTime.Minute() == 0 {
					Execute(TriggerTypeHour, nowTime)
				}
				// 触发eightHour
				if nowTime.Hour()%8 == 0 {
					Execute(TriggerTypeEightHour, nowTime)
				}
				// 触发day 0点触发
				if nowTime.Hour() == 0 && nowTime.Minute() == 0 {
					Execute(TriggerTypeDay, nowTime)
				}
				// 触发week 周日0点触发
				if nowTime.Weekday() == time.Sunday && nowTime.Hour() == 0 && nowTime.Minute() == 0 {
					Execute(TriggerTypeWeek, nowTime)
				}
				// 触发month 1号0点触发
				if nowTime.Day() == 1 && nowTime.Hour() == 0 && nowTime.Minute() == 0 {
					Execute(TriggerTypeMonth, nowTime)
				}
			}()
		}
	}
}

// restartTimerHandler 重启定时器
func restartTimerHandler() {
	// 设置重试次数
	maxRetries := 5
	retryCount := 0

	for {
		select {
		case <-time.After(5 * time.Minute): // 等待5分钟后重试
			if retryCount >= maxRetries {
				logUtilPlus.ErrorLog("定时器重启失败，达到最大重试次数")
				return
			}
			logUtilPlus.InfoLog("重新启动定时器，重试次数: %d", retryCount+1)
			go timerHandler()
			return
		}
		retryCount++
	}
}
