package m9z

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

	"math"
	"time"
)

type LgnLatData struct {
	Lgn float64 // 经度
	Lat float64 // 纬度
	Loc *time.Location
}

// 经纬度参数
func LgnLatRead(deviceId string) (*LgnLatData, error) {

	ll := new(LgnLatData)
	cmd, err := ReadCmd(deviceId, lgnLat, "读取经纬度参数")
	if err != nil {
		return nil, err
	}
	data := cmd.Data
	lgn := float64(binary.LittleEndian.Uint32(data[0:4])) / 1000000
	lat := float64(binary.LittleEndian.Uint32(data[4:8])) / 1000000
	loc := float64(binary.LittleEndian.Uint32(data[8:len(data)])) / 1000000
	ll.Lgn = lgn
	ll.Lat = lat
	timezone, err := FloatToTimezone(loc)
	if err != nil {
		return nil, err
	}
	ll.Loc = timezone

	return ll, nil
}
func LgnLatWrite(deviceId string, data *LgnLatData) error {
	// 将浮点型经纬度转换为字节编码（兼容原Read逻辑）
	buf := make([]byte, 12)

	// 1. 处理经度（4字节）
	lgnInt := uint32(math.Round(data.Lgn * 1000000))
	binary.LittleEndian.PutUint32(buf[0:4], lgnInt)

	// 2. 处理纬度（4字节）
	latInt := uint32(math.Round(data.Lat * 1000000))
	binary.LittleEndian.PutUint32(buf[4:8], latInt)

	// 3. 处理时区（4字节）
	// 从time.Location解析出UTC偏移小时数（含小数）
	offsetHours, err := getTimezoneOffset(data.Loc)
	if err != nil {
		return err
	}
	offsetInt := uint32(math.Round(offsetHours * 1000000))
	binary.LittleEndian.PutUint32(buf[8:12], offsetInt)
	writeResp, err := WriteCmd(deviceId, lgnLat, buf, "写入经纬度参数")
	if err != nil {
		return err
	}
	if !writeResp.Success {
		return gerror.New("设置失败")
	}
	return nil
}

// 从time.Location中解析UTC偏移小时数（支持正负）
func getTimezoneOffset(loc *time.Location) (float64, error) {
	// 任取一个时间点计算偏移（固定时区偏移不会变化）
	t := time.Date(2023, 1, 1, 0, 0, 0, 0, loc)
	_, offsetSec := t.Zone()

	// 转换为小时（含小数）
	offsetHours := float64(offsetSec) / 3600.0
	if offsetHours < -12 || offsetHours > 14 {
		return 0, fmt.Errorf("invalid timezone offset: %f", offsetHours)
	}
	return offsetHours, nil
}

// FloatToTimezone 将float64时区值转换为 *time.Location
// 输入示例: 8.0 → UTC+8, -5.5 → UTC-5:30
func FloatToTimezone(offset float64) (*time.Location, error) {
	// 验证范围 (-12.0 到 +14.0)
	if offset < -12.0 || offset > 14.0 {
		return nil, fmt.Errorf("时区偏移量超出有效范围 (-12.0 到 +14.0)")
	}

	// 分解小时和分钟
	hours := int(math.Floor(offset))
	minutes := int(math.Round((offset - float64(hours)) * 60))

	// 处理负数情况
	if offset < 0 {
		minutes = -minutes
	}

	// 创建固定时区
	name := fmt.Sprintf("UTC%+03d:%02d", hours, minutes)
	return time.FixedZone(name, hours*3600+minutes*60), nil
}
