package m9z

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

// 对应C的db_ble_extern_t结构体（简化版，使用bool型Enable）
type BluetoothConfig struct {
	Enable     bool   // 离线监控使能（false=禁止，true=允许/0xAA）
	OfflineMin uint8  // 离线时间（分钟数）
	BleName    string // 蓝牙名称（最大20字节） 不支持中文
}

func BluetoothRead(deviceId string) (*BluetoothConfig, error) {
	// 1. 读取指令
	cmd, err := ReadCmd(deviceId, bluetooth, "设备蓝牙配置读取")
	if err != nil {
		errMsg := fmt.Sprintf("读取设备%s蓝牙配置失败: %v", deviceId, err)

		return nil, gerror.New(errMsg)
	}

	data := cmd.Data

	// 2. 校验基础长度（至少2字节：离线监控+离线时间）
	const minDataLen = 2
	if len(data) < minDataLen {
		errMsg := fmt.Sprintf("蓝牙配置数据长度不足，至少需要%d字节，实际收到%d字节", minDataLen, len(data))

		return nil, gerror.New(errMsg)
	}

	// 3. 解析基础字段（固定2字节）
	var bleConfig BluetoothConfig
	bleConfig.Enable = data[0] == 0xAA // 0xAA对应true（允许），其他为false（禁止）
	bleConfig.OfflineMin = data[1]     // 离线时间

	// 4. 解析蓝牙名称（动态长度，最多20字节）
	nameBytes := data[2:] // 取基础字段后的所有字节
	if len(nameBytes) > 20 {
		nameBytes = nameBytes[:20] // 超过20字节则截断
	}
	// 去掉名称末尾的空字符（设备返回的结束符）
	bleConfig.BleName = string(bytes.TrimRight(nameBytes, "\x00"))
	return &bleConfig, nil
}

// BluetoothWrite 写入蓝牙配置到设备（修复所有核心问题）
func BluetoothWrite(deviceId string, bleConfig *BluetoothConfig) error {
	// 1. 精准参数校验（拆分判断，提示语匹配）
	if bleConfig == nil {
		errMsg := "蓝牙配置结构体为nil，无法写入"

		return gerror.New(errMsg)
	}
	nameBytes := []byte(bleConfig.BleName)
	if len(nameBytes) > 20 {
		errMsg := fmt.Sprintf("蓝牙名称超长，最大支持20字节，实际传入%d字节", len(nameBytes))

		return gerror.New(errMsg)
	}
	// 校验1：是否包含中文/非ASCII字符
	if hasChinese(bleConfig.BleName) {
		errMsg := fmt.Sprintf("设备[%s]蓝牙名称包含中文/非ASCII字符，仅支持英文/数字/符号等ASCII字符", deviceId)

		return gerror.New(errMsg)
	}

	// 2. 构造缓冲区：2字节基础字段 + 动态长度蓝牙名称
	buf := make([]byte, 2) // 先初始化基础字段缓冲区
	// 编码离线监控使能（Byte0：0=禁止，0xAA=允许）
	if bleConfig.Enable {
		buf[0] = 0xAA
	} else {
		buf[0] = 0x00
	}
	// 编码离线时间（Byte1）
	buf[1] = bleConfig.OfflineMin

	// 追加蓝牙名称（仅追加一次，修复重复追加问题）
	buf = append(buf, nameBytes...)

	// 调试日志：打印最终缓冲区（长度+十六进制）
	//g.Log().Debugf("Bluetooth Write raw data: len=%d , hex=% X", len(buf), buf)

	// 3. 发送写入命令
	writeResp, err := WriteCmd(deviceId, bluetooth, buf, "设备蓝牙配置写入")
	if err != nil {
		errMsg := fmt.Sprintf("设备[%s]蓝牙配置写入命令调用失败", deviceId)
		return gerror.Wrapf(err, errMsg)
	}

	// 4. 检查写入响应状态（修复err为nil的问题）
	if !writeResp.Success {
		errMsg := fmt.Sprintf("设备[%s]蓝牙配置写入失败，响应状态为失败", deviceId)

		// 手动构造错误，避免Wrapf传入nil
		return gerror.New(errMsg)
	}

	// 5. 写入成功日志（修复切片越界问题：用buf[2:]而非固定22）
	//bleNameStr := string(bytes.TrimRight(buf[2:], "\x00"))
	//g.Log().Infof("设备%s蓝牙配置写入成功，离线监控使能：%v，离线时间：%d分钟，蓝牙名称：%s",
	//	deviceId, bleConfig.Enable, bleConfig.OfflineMin, bleNameStr)

	return nil
}

// hasChinese 辅助函数：判断字符串是否包含中文（或非ASCII字符）
func hasChinese(s string) bool {
	for _, r := range s {
		// 中文Unicode范围：0x4E00-0x9FFF，同时拦截所有＞127的非ASCII字符
		if r > 127 || (r >= 0x4E00 && r <= 0x9FFF) {
			return true
		}
	}
	return false
}
