package m9z

import (
	"fmt"
	"github.com/gogf/gf/v2/errors/gerror"

	"tgk-touch/internal/global"
	"tgk-touch/internal/module/maincontrollerClient"
)

const (
	FrameHeader   = 0xEE
	FrameFooter   = 0xFF
	CmdRead       = 0x01
	CmdWrite      = 0x02
	ResponseFlag  = 0x80 // D7位掩码
	MaxPacketSize = 256
)

// 读取命令结构
type ReadCommand struct {
	Instruction byte
	Index       byte
}

// 写入命令结构
type WriteCommand struct {
	Instruction byte
	Index       byte
	Data        []byte
	IsUpdate    bool
}

// 读取响应结构
type ReadResponse struct {
	Instruction byte
	Index       byte
	Data        []byte
}

// 写入响应结构
type WriteResponse struct {
	Instruction byte
	Index       byte
	Success     bool
}

// 校验和计算
func calCheckSum(data []byte) byte {
	sum := byte(0x33)
	for _, b := range data {
		sum += b
	}
	return sum
}

// 构建读取命令帧
func BuildReadCommand(cmd ReadCommand) []byte {
	frame := []byte{FrameHeader}
	payload := []byte{cmd.Instruction, CmdRead, cmd.Index}
	frame = append(frame, payload...)
	frame = append(frame, calCheckSum(payload))
	frame = append(frame, FrameFooter)
	return frame
}

// 构建写入命令帧
func BuildWriteCommand(cmd WriteCommand) []byte {
	frame := []byte{FrameHeader}
	payload := []byte{cmd.Instruction, CmdWrite, cmd.Index}
	if len(cmd.Data) > 0 && !cmd.IsUpdate {
		payload = append(payload, byte(len(cmd.Data)))
	}
	payload = append(payload, cmd.Data...)
	frame = append(frame, payload...)
	frame = append(frame, calCheckSum(payload))
	frame = append(frame, FrameFooter)
	return frame
}

// 解析接收帧
func ParseFrame(data []byte) (interface{}, error) {
	g.Log().Debugf("ParseFrame:[% X]", data)
	s := ""
	for i, d := range data {
		if i == 0 {

		}
		s += fmt.Sprintf("0x%X,", d)
	}
	//g.Log().Debugf("\n ParseFrame:{%s} ", s)
	// 基本长度检查
	if len(data) < 5 {
		return nil,
			NewReadError("frame too short")
	}

	// 验证帧头帧尾
	if data[0] != FrameHeader || data[len(data)-1] != FrameFooter {
		return nil, NewReadError("invalid frame header or footer")
	}

	// 提取有效载荷和校验和
	payload := data[1 : len(data)-2]
	receivedCS := data[len(data)-2]

	// 计算校验和
	if calCheckSum(payload) != receivedCS {
		return nil, NewReadError("checksum mismatch")
	}

	// 解析指令类型
	if len(payload) < 2 {
		return nil, NewReadError("invalid payload length")
	}

	instruction := payload[0]
	cmdType := payload[1]

	// 判断是否是响应帧（D7位是否置1）
	isResponse := (instruction & ResponseFlag) != 0

	switch {
	case isResponse && cmdType == CmdRead:
		// 特殊处理实际通断情况查询指令 (0x19) 的响应
		// 该指令返回的数据结构较为特殊，可能包含多个字段，需要专门的解析逻辑
		// 或者复用 parseReadResponse，但在解析 Data 时进行特定处理
		return parseReadResponse(payload)
	case isResponse && cmdType == CmdWrite:
		return parseWriteResponse(payload)
	default:
		return nil, gerror.New("unsupported command type")
	}
}

// 解析读取响应
func parseReadResponse(payload []byte) (*ReadResponse, error) {
	if len(payload) < 4 {
		return nil, gerror.New("invalid read response format")
	}

	index := payload[2]
	dataLength := payload[3]

	if len(payload) < 4+int(dataLength) {
		return nil, gerror.New("data length mismatch")
	}

	return &ReadResponse{
		Instruction: payload[0],
		Index:       index,
		Data:        payload[4 : 4+dataLength],
	}, nil
}
func parseReadBlockResponse(payload []byte) (*ReadResponse, error) {
	if len(payload) < 4 {
		return nil, gerror.New("invalid read response format")
	}

	index := payload[2]
	dataLength := payload[3:5]
	le := BytesToUint16LE(dataLength)
	if len(payload) < 4+int(le) {
		return nil, gerror.New("data length mismatch")
	}

	return &ReadResponse{
		Instruction: payload[0],
		Index:       index,
		Data:        payload[5 : 5+le],
	}, nil
}

// 解析写入响应
func parseWriteResponse(payload []byte) (*WriteResponse, error) {
	if len(payload) < 5 {
		return nil, gerror.New("invalid write response format")
	}

	index := payload[2]
	dataLength := payload[3]

	if dataLength != 1 {
		return nil, gerror.New("invalid data length in write response")
	}

	success := payload[4] == 0x01
	return &WriteResponse{
		Instruction: payload[0],
		Index:       index,
		Success:     success,
	}, nil
}

// 辅助函数：将数据转换为小端格式的uint16
func BytesToUint16LE(b []byte) uint16 {
	if len(b) < 2 {
		return 0
	}
	return uint16(b[0]) | uint16(b[1])<<8
}

// 辅助函数：将uint16转换为小端格式的字节切片
func Uint16ToBytesLE(n uint16) []byte {
	return []byte{byte(n), byte(n >> 8)}
}

/*
	func pushCommand(cmd []byte) ([]byte, error) {
		push.Lock()
		defer push.Unlock()
		fmt.Printf("Push Command :% X\n", cmd)
		conn, err := net.Dial("tcp", "10.10.100.254:8899")
		if err != nil {
			g.Log().Infof("%+v\n", err)
			return nil, err
		}
		defer conn.Close()
		_, err = conn.Write(cmd)
		if err != nil {
			g.Log().Infof("%+v\n", err)
			return nil, err
		}
		buf := make([]byte, 128)
		n, err := conn.Read(buf)
		if err != nil {
			g.Log().Infof("%+v\n", err)
			return nil, err
		}
		return buf[:n], nil
	}
*/
func pushCommand(deviceId string, cmd []byte, detail string) ([]byte, error) {

	var result []byte
	g.Log().Debugf("push cmd:[% X] ", cmd)

	err := maincontrollerClient.DeviceCallByDeviceID(
		deviceId,
		"/lampControl",
		"", cmd, &result, func(deviceID, method string, params, result interface{}) (deviceType, cmdDetail, cmdDisplay, resultDisplay string) {
			deviceType = "tgk"
			cmdDetail = detail
			return
		})
	if err != nil {
		return nil, gerror.Wrapf(err, "单灯控制命令 deviceID={%v} cmd={% X} 下发失败", deviceId, cmd)
	}
	return result, nil

}

func ReadCmd(deviceId string, cmd M9zCtrl, detail string, idx ...uint) (*ReadResponse, error) {
	var idxEnd byte
	idxEnd = 0x00
	if len(idx) > 0 {
		idxEnd = byte(idx[0])
	}
	readCmd := ReadCommand{Instruction: byte(cmd), Index: idxEnd}
	readFrame := BuildReadCommand(readCmd)
	cmdRespData, err := pushCommand(deviceId, readFrame, detail)
	if err != nil {
		return nil, err
	}
	frame, err := ParseFrame(cmdRespData)
	if err != nil {
		return nil, err
	}
	return frame.(*ReadResponse), err
}

// 定义专属的标记常量（根据业务场景选择合适的值，这里用0xff对应原逻辑的-1） 标记是升级
const UpdateMarker byte = 0xff // 特殊标记值，替代原逻辑中的-1

func WriteCmd(deviceId string, cmd M9zCtrl, data []byte, detail string, idx ...uint8) (*WriteResponse, error) {
	isUpdate := false
	// 4. 构建写入命令
	wIdx := byte(0x00)
	if len(idx) > 0 {
		wIdx = idx[0]
		// 准确判断是否是特殊标记值（类型完全匹配，无隐式转换）
		if wIdx == UpdateMarker {
			isUpdate = true
			// 这里添加标记值的处理逻辑（根据你的业务需求定制）
			// 示例：重置为默认值、执行特定业务逻辑等
			wIdx = 0x00 // 示例操作：将标记值重置为默认值
		}
	}
	writeCmd := WriteCommand{
		Instruction: byte(cmd),
		Index:       wIdx,
		Data:        data,
		IsUpdate:    isUpdate,
	}
	writeFrame := BuildWriteCommand(writeCmd)

	cmdRespData, err := pushCommand(deviceId, writeFrame, detail)
	if err != nil {
		return nil, err
	}
	resp, err := ParseFrame(cmdRespData)
	if err != nil {
		return nil, err
	}
	return resp.(*WriteResponse), nil
}
func percentToHex(percent int) byte {
	if percent < 0 {
		return 0x00 // 低于0%视为0%
	}
	if percent > 100 {
		return 0x64 // 超过100%视为100%
	}
	return byte(percent) // 直接转换
}
func hexToPercent(hexValue byte) int {
	if hexValue > 0x64 {
		err := fmt.Errorf("非法十六进制值: 0x%02X（超过0x64）", hexValue)
		g.Log().Infof("%+v", err)
		return 0
	}
	return int(hexValue)
}
