package m9z // 插件
import (
	"encoding/binary"
	"fmt"
	"github.com/gogf/gf/v2/errors/gerror"

	"sort"
	"tgk-touch/internal/global"
	"time"
)

var (
	DefaultStartTask ControlTask = ControlTask{
		TimeType: 0,
		Loops: []TaskLoop{
			{
				0, true, 70,
			},
			{
				1, true, 70,
			},
			{
				2, true, 70,
			},
			{
				3, true, 70,
			},
			{
				4, true, 70,
			},
			{
				5, true, 70,
			},
			{
				6, true, 70,
			},
			{
				7, true, 70,
			},
			{
				8, true, 70,
			},
			{
				9, true, 70,
			},
		},
	}
	DefaultMiddleTask MiddleControlTask = MiddleControlTask{
		[]ControlTask{
			ControlTask{

				TimeType: 0,
				Loops: []TaskLoop{
					{
						0, true, 70,
					},
					{
						1, true, 70,
					},
					{
						2, true, 70,
					},
					{
						3, true, 70,
					},
					{
						4, true, 70,
					},
					{
						5, true, 70,
					},
					{
						6, true, 70,
					},
					{
						7, true, 70,
					},
					{
						8, true, 70,
					},
					{
						9, true, 70,
					},
				},
			},
		},
	}
	DefaultStopTask ControlTask = ControlTask{

		TimeType: 0,
		Loops: []TaskLoop{
			{
				0, false, 70,
			},
			{
				1, false, 70,
			},
			{
				2, false, 70,
			},
			{
				3, false, 70,
			},
			{
				4, false, 70,
			},
			{
				5, false, 70,
			},
			{
				6, false, 70,
			},
			{
				7, false, 70,
			},
			{
				8, false, 70,
			},
			{
				9, false, 70,
			},
		},
	}
)

func init() {
	parse, _ := time.ParseInLocation("2006-01-02 15:04:05", "2025-06-05 19:00:00", time.Local)

	DefaultStartTask.ExecTime = parse
	for i, c := range DefaultMiddleTask.ControlTaskList {
		p, _ := time.ParseInLocation("2006-01-02 15:04:05", "2025-06-05 20:00:00", time.Local)
		c.ExecTime = p
		DefaultMiddleTask.ControlTaskList[i] = c
	}
	parse, _ = time.ParseInLocation("2006-01-02 15:04:05", "2025-06-05 07:00:00", time.Local)
	DefaultStartTask.ExecTime = parse
}

func IsTaskInitRead(deviceId string) (bool, error) {
	read, err := ManualRead(deviceId)
	if err != nil {
		return false, err
	}
	return read.BackupByte1 == 1, nil
}
func SetIsTaskInitRead(deviceId string, b bool) error {
	read, err := ManualRead(deviceId)
	if err != nil {
		return err
	}
	if b {
		read.BackupByte1 = 1
	} else {
		read.BackupByte1 = 0
	}
	return ManualWrite(deviceId, read)
}

type TaskLoop struct {
	Index  uint  `json:"index"` // 0 D0 回路0
	TurnOn bool  `json:"turnOn"`
	Pwm    uint8 `json:"pwm"` // 功率百分比
}

// 控制任务配置
type ControlTask struct {
	ExecTime time.Time  `json:"execTime"` // "2006-01-02 15:04:05" 格式时间
	TimeType int        `json:"timeType"` // 0 定时 1经纬
	Loops    []TaskLoop `json:"loops"`
}
type MiddleControlTask struct {
	ControlTaskList []ControlTask `json:"controlTaskList"`
}

func ControlTaskToTaskProgram(task ControlTask, idx uint8) (*TaskProgram, error) {
	if uint8(0) > idx || idx > uint8(2) {
		idx = 0
	}
	// 1. 创建任务程序对象
	program := &TaskProgram{
		Index: idx,
	}

	// 2. 解析执行时间
	eTime := task.ExecTime
	g.Log().Debugf("task:%+v\ntask.ExecTime %+v , eTime:%+v,hour:%d,min:%d", task, task.ExecTime, eTime, eTime.Hour(), eTime.Minute())
	minValue := uint32(eTime.Hour()*60 + eTime.Minute())
	var cmpInstruction TaskInstruction
	// 3. 添加时间比较指令
	if task.TimeType == 0 {
		cmpInstruction = TaskInstruction{
			Type:  0x01 << 28, // CMP指令类型
			Param: 0x01 << 24,
			Value: minValue,
		}
	} else {
		cmpInstruction = TaskInstruction{
			Type:  0x01 << 28,
			Param: 0x02 << 24,
			Value: minValue,
		}
	}

	program.Instructions = append(program.Instructions, cmpInstruction)

	// 开灯任务需要两条指令：
	// 1. 开启所有回路继电器
	var openLoopValue uint32
	var closeLoopValue uint32
	for _, loop := range task.Loops {
		if loop.TurnOn {
			openLoopValue |= (0x1 << loop.Index)
		} else {
			closeLoopValue |= (0x1 << loop.Index)
		}
		if loop.Pwm > 100 {
			loop.Pwm = 100
		}
		loopIndex := (0x1 << loop.Index)
		loopIndex |= (0x1 << loop.Index)
		// 修复类型不匹配问题
		pwmValue := (uint32(loopIndex) << 12) | uint32(loop.Pwm)

		pwmInstruction := TaskInstruction{
			Type:  0x4 << 28, // OUTPUT指令
			Param: 0x03 << 24,
			Value: pwmValue,
		}
		program.Instructions = append(program.Instructions, pwmInstruction)
	}
	if openLoopValue != 0 {
		openLoopValue = (openLoopValue << 12) | 0x01
	}
	if closeLoopValue != 0 {
		closeLoopValue = (closeLoopValue << 12) | 0x00
	}

	openLoopIns := TaskInstruction{
		Type:  0x04 << 28, // OUTPUT指令
		Param: 0x01 << 24,
		Value: openLoopValue,
	}
	closeLoopIns := TaskInstruction{
		Type:  0x04 << 28, // OUTPUT指令
		Param: 0x01 << 24,
		Value: closeLoopValue,
	}

	program.Instructions = append(program.Instructions, openLoopIns, closeLoopIns)
	// 2. 设置PWM亮度
	// 5. 设置任务大小（现在有3条指令）
	program.Size = uint8(len(program.Instructions))

	return program, nil
}

func TaskProgramToControlTask(program *TaskProgram) (*ControlTask, error) {
	task := &ControlTask{
		TimeType: 0, // 默认定时类型
		// 初始化所有10个回路（0-9）
		Loops: make([]TaskLoop, 10),
	}

	// 初始化所有回路为关闭状态
	for i := range task.Loops {
		task.Loops[i] = TaskLoop{
			Index:  uint(i),
			TurnOn: false,
			Pwm:    0,
		}
	}

	foundTimeInstruction := false

	// 解析所有指令
	for _, ins := range program.Instructions {
		g.Log().Debugf("Found instruction: %+v,type %+v isTime %+v", ins, ins.Type, ins.Type == 0x01)
		switch ins.Type {
		case 0x01: // 时间命令
			foundTimeInstruction = true
			minutes := ins.Value
			hour := minutes / 60
			minute := minutes % 60
			parse, err := time.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%s %02d:%02d:00", time.Now().Format(time.DateOnly), hour, minute), time.Local)
			if err != nil {
				return nil, gerror.Wrapf(err, "failed to parse time")
			}
			task.ExecTime = parse

			// 处理时间类型
			switch ins.Param {
			case 0x01:
				task.TimeType = 0 // 定时
			case 0x02:
				task.TimeType = 1 // 经纬
			}

		case 0x04: // OUTPUT指令
			paramType := ins.Param
			switch paramType {
			case 0x01: // 继电器状态命令
				relayValue := ins.Value
				// 判断是开还是关
				isOpen := (relayValue & 1) == 1
				// 获取开启掩码（高12位）
				onMask := (relayValue >> 12) & 0xFFF

				// 颠倒位顺序 - 低位对应低索引回路
				reversedOnMask := uint32(0)
				for i := 0; i < 12; i++ {
					originalBit := (onMask >> i) & 0x1
					reversedOnMask |= (originalBit << (11 - i))
				}

				str := fmt.Sprintf("%12b", reversedOnMask)
				for i := 0; i < len(str)-2; i++ {
					if str[i] == '1' {
						if isOpen {
							task.Loops[i].TurnOn = true
							g.Log().Debugf("isOpen %+v ,loop %+v ,on %q ,t :%+v", isOpen, i, str[i], true)

						} else {
							task.Loops[i].TurnOn = false
							g.Log().Debugf("isOpen %+v ,loop %+v ,on %q ,t :%+v", isOpen, i, str[i], false)

						}
					}
				}

			case 0x03: // PWM指令
				pwmValue := ins.Value
				// 高12位：通道掩码，低12位：PWM值
				channelMask := (pwmValue >> 12) & 0xFFF
				pwmVal := uint8(pwmValue & 0xFF) // 取低8位作为PWM值

				// 处理每个回路的PWM值
				for i := 0; i < 12; i++ {
					if i < len(task.Loops) && (channelMask&(1<<i) != 0) {
						task.Loops[i].Pwm = pwmVal
					}
				}
			}
		}
	}

	// 如果没有找到时间指令，返回错误
	if !foundTimeInstruction {
		return nil, fmt.Errorf("missing time instruction in task program %+v", program.Instructions)
	}

	/*	// 过滤掉保持默认关闭状态的回路
		activeLoops := make([]TaskLoop, 0, len(task.Loops))
		for _, loop := range task.Loops {
			if loop.TurnOn || loop.Pwm > 0 {
				activeLoops = append(activeLoops, loop)
			}
		}
		task.Loops = activeLoops*/

	return task, nil
}

func MiddleControlTaskToTaskProgram(middle MiddleControlTask, idx uint8) (*TaskProgram, error) {
	sort.Slice(middle.ControlTaskList, func(i, j int) bool {
		t1 := middle.ControlTaskList[i].ExecTime
		t2 := middle.ControlTaskList[i].ExecTime
		return t1.Before(t2)
	})
	if idx < 0 || idx > 2 {
		idx = 0
	}
	program := &TaskProgram{
		Index: idx,
	}
	fmt.Printf("middleControlTaskToTaskProgram middle:%+v\n", middle)

	for _, task := range middle.ControlTaskList {

		// 2. 解析执行时间
		eTime := task.ExecTime
		fmt.Printf("task:%+v\ntask.ExecTime %+v , eTime:%+v,hour:%d,min:%d\n", task, task.ExecTime, eTime, eTime.Hour(), eTime.Minute())

		minValue := uint32(eTime.Hour()*60 + eTime.Minute())
		var cmpInstruction TaskInstruction
		// 3. 添加时间比较指令
		if task.TimeType == 0 {
			cmpInstruction = TaskInstruction{
				Type:  0x01 << 28, // CMP指令类型
				Param: 0x5 << 24,
				Value: minValue,
			}
		} else {
			cmpInstruction = TaskInstruction{
				Type:  0x01 << 28,
				Param: 0x04 << 24,
				Value: minValue,
			}
		}

		program.Instructions = append(program.Instructions, cmpInstruction)

		// 开灯任务需要两条指令：
		// 1. 开启所有回路继电器
		var openLoopValue uint32
		var closeLoopValue uint32
		// 2. PWM指令（针对每个回路）
		pwmMap := make(map[uint8][]uint) // 按PWM值分组
		for _, loop := range task.Loops {
			if loop.Pwm > 0 {
				pwmMap[loop.Pwm] = append(pwmMap[loop.Pwm], loop.Index)
			}
		}
		// 为每个PWM值创建指令
		for pwmVal, indices := range pwmMap {
			channelMask := uint32(0)
			for _, idx2 := range indices {
				if idx2 < 12 {
					channelMask |= (1 << idx2)
				}
			}

			pwmInstruction := TaskInstruction{
				Type:  0x4 << 28,  // OUTPUT指令
				Param: 0x03 << 24, // PWM类型
				Value: (channelMask << 12) | uint32(pwmVal),
			}
			program.Instructions = append(program.Instructions, pwmInstruction)
		}
		for _, loop := range task.Loops {
			if loop.TurnOn {
				openLoopValue |= (0x1 << loop.Index)
			} else {
				closeLoopValue |= (0x1 << loop.Index)
			}
		}
		if openLoopValue != 0 {
			openLoopValue = (openLoopValue << 12) | 0x01
		}
		if closeLoopValue != 0 {
			closeLoopValue = (closeLoopValue << 12) | 0x00
		}
		openLoopIns := TaskInstruction{
			Type:  0x04 << 28, // OUTPUT指令
			Param: 0x01 << 24,
			Value: openLoopValue,
		}
		if openLoopValue != 0 {
			program.Instructions = append(program.Instructions, openLoopIns)

		}
		closeLoopIns := TaskInstruction{
			Type:  0x04 << 28, // OUTPUT指令
			Param: 0x01 << 24,
			Value: closeLoopValue,
		}

		if closeLoopValue != 0 {
			program.Instructions = append(program.Instructions, closeLoopIns)
		}

	}
	// 中间任务需要循环
	loopIns := TaskInstruction{
		Type:  0x2 << 28,
		Param: ((0x1 /*跳转使能*/) & 0xF) << 24,
		Value: (((0 /*跳转到第几步*/) & 0xFF) << 16) | (((0 /*最大次数*/) & 0xFF) << 8),
	}
	program.Instructions = append(program.Instructions, loopIns)
	program.Size = uint8(len(program.Instructions))
	return program, nil
}

func TaskProgramToMiddleControlTask(program *TaskProgram) (*MiddleControlTask, error) {
	middle := &MiddleControlTask{
		ControlTaskList: make([]ControlTask, 0),
	}

	// 存储当前正在解析的任务
	var currentTask *ControlTask
	taskIndex := 0

	for i, ins := range program.Instructions {
		insType := ins.Type
		paramType := ins.Param

		g.Log().Debugf("解析指令 %d: Type=0x%X, Param=0x%X, Value=0x%08X", i, insType, paramType, ins.Value)
		switch insType {
		case 0x01: // 时间比较指令
			// 完成前一个任务（如果有）
			if currentTask != nil {
				middle.ControlTaskList = append(middle.ControlTaskList, *currentTask)
				taskIndex++
			}

			// 创建新任务
			currentTask = &ControlTask{
				Loops: make([]TaskLoop, 10), // 10个回路的默认配置
			}

			// 初始化所有回路状态
			for j := range currentTask.Loops {
				currentTask.Loops[j] = TaskLoop{
					Index:  uint(j),
					TurnOn: false,
					Pwm:    0,
				}
			}

			// 解析时间
			minutes := ins.Value
			hour := minutes / 60
			minute := minutes % 60
			parse, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %02d:%02d", time.Now().Format(time.DateOnly), hour, minute), time.Local)

			if err != nil {
				return nil, gerror.Wrap(err, "parse time error")
			}
			currentTask.ExecTime = parse

			// 解析时间类型
			switch paramType {
			case 0x5:
				currentTask.TimeType = 0 // 定时
			case 0x4:
				currentTask.TimeType = 1 // 经纬
			default:
				g.Log().Warnf("未知的时间类型: 0x%X", paramType)
				currentTask.TimeType = 0
			}

			g.Log().Debugf("时间指令: %s, 时间类型: %d ,分钟数：%d", currentTask.ExecTime, currentTask.TimeType, minutes)
		case 0x04: // OUTPUT指令
			if currentTask == nil {
				g.Log().Warnf("在时间指令前发现OUTPUT指令，忽略")
				continue
			}

			switch paramType {
			case 0x01: // 继电器状态命令

				value := ins.Value
				// 判断是开还是关
				isOpen := (value & 1) == 1
				onMask := (value >> 12) & 0xFFF

				// 输出原始掩码值（二进制12位格式）
				g.Log().Debugf("开关命令%+v", isOpen)
				g.Log().Debugf("原始继电器掩码: %012b (onMask = 0x%03X)", onMask, onMask)

				// 颠倒位顺序 - 低位对应低索引回路
				reversedOnMask := uint32(0)
				for j := 0; j < 12; j++ {
					originalBit := (onMask >> j) & 0x1
					reversedOnMask |= (originalBit << (11 - j))
				}

				// 输出反转后的掩码值
				str := fmt.Sprintf("%012b", reversedOnMask)
				g.Log().Debugf("反转后继电器掩码: %s (reversedOnMask = 0x%03X)", str, reversedOnMask)

				// 逐个输出每个回路的位状态
				g.Log().Debug("按位解析回路状态:")
				for j := 0; j < len(str)-2; j++ {
					if j >= len(currentTask.Loops) {
						break
					}

					if str[j] == '1' {
						if isOpen {
							currentTask.Loops[j].TurnOn = str[j] == '1' && isOpen
							g.Log().Debugf("loop %+v ,on %q ,t :%+v", j, str[j], true)
						} else {
							currentTask.Loops[j].TurnOn = false
							g.Log().Debugf("loop %+v ,on %q ,t :%+v", j, str[j], false)

						}
					}

				}

			case 0x03: // PWM指令
				value := ins.Value
				channelMask := (value >> 12) & 0xFFF
				pwmVal := uint8(value & 0xFF)

				// 输出原始掩码值
				g.Log().Debugf("原始PWM掩码: %012b (channelMask = 0x%03X), PWM值: %d", channelMask, channelMask, pwmVal)

				// 颠倒位顺序 - 低位对应低索引回路
				reversedChannelMask := uint32(0)
				for j := 0; j < 12; j++ {
					originalBit := (channelMask >> j) & 0x1
					reversedChannelMask |= (originalBit << (11 - j))
				}

				// 输出反转后的掩码值
				str := fmt.Sprintf("%012b", reversedChannelMask)
				g.Log().Debugf("反转后PWM掩码: %s (reversedChannelMask = 0x%03X)", str, reversedChannelMask)

				// 设置每个回路的PWM值
				for j := 0; j < len(str); j++ {
					if j >= len(currentTask.Loops) {
						break
					}

					if str[j] == '1' {
						g.Log().Debugf("  设置回路 %d PWM值: %d%%", j, pwmVal)
						currentTask.Loops[j].Pwm = pwmVal
					}
				}
			}

		case 0x02: // 循环指令
			g.Log().Debug("检测到循环指令，跳过")

		default:
			g.Log().Warnf("未知的指令类型: 0x%X", insType)
		}
	}

	// 添加最后一个任务（如果有）
	if currentTask != nil {
		middle.ControlTaskList = append(middle.ControlTaskList, *currentTask)
	}

	g.Log().Debugf("成功解析 %d 个控制任务", len(middle.ControlTaskList))

	return middle, nil
}

// 写入开始任务到设备
func StartTaskWriteByTaskCfg(deviceId string, idx uint8, task ControlTask) error {
	// 1. 将控制任务转换为任务程序
	tp, err := ControlTaskToTaskProgram(task, idx)
	if err != nil {
		return err
	}

	// 2. 使用CMD 0x13写入开始任务
	return StartTaskWrite(deviceId, tp)
}

// 写入任务程序到设备
func StartTaskWrite2(deviceId string, program *TaskProgram) error {
	// 1. 构造数据缓冲区 (1字节大小 + 每个指令4字节)
	buf := make([]byte, 1+4*len(program.Instructions))
	buf[0] = program.Size

	offset := 1
	for _, ins := range program.Instructions {
		// 2. 组合指令 (类型在高4位)
		instruction := uint32(ins.Type) << 28

		/*// 3. 根据指令类型组合参数
		switch len(ins.Params) {
		case 1:
			instruction |= ins.Param & 0x0FFFFFFF
		case 2:
			instruction |= (ins.Param & 0x0F) << 24
			instruction |= ins.Value & 0x00FFFFFF
		case 3:
			instruction |= (ins.Param & 0x0F) << 24
			instruction |= (ins.Value & 0xFFFF) << 8
			instruction |= ins.Params[2] & 0xFF
		}*/

		// 4. 写入小端序
		binary.LittleEndian.PutUint32(buf[offset:offset+4], instruction)
		offset += 4
	}

	// 5. 发送写入命令

	return StartTaskWrite(deviceId, program)
}
