package adl400TtyApi

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

	"github.com/towgo/towgo/towgo"
	"math"
	"tgk-touch/internal/global"
	"tgk-touch/internal/library/ADL400"
	"tgk-touch/internal/module/basicInfo/deviceManagement"
	"time"
)

func readPhaseData(rpc towgo.JsonRpcConnection) {
	var p struct {
		CommUid string `json:"comm_uid"`
	}
	rpc.ReadParams(&p)

	addr := getMeterAddr(p.CommUid)
	rtuCommUid := p.CommUid
	var mp deviceManagement.MeterPower
	totalEnergy, aEnergy, bEnergy, cEnergy, err := getMc().ReadEnergy(rtuCommUid, addr)
	if err != nil {
		panic(err)
	}
	mp.TotalActiveEnergy = math.Round(totalEnergy*100) / 100
	mp.AEnergy = math.Round(aEnergy*100) / 100
	mp.BEnergy = math.Round(bEnergy*100) / 100
	mp.CEnergy = math.Round(cEnergy*100) / 100

	_, aVoltage, bVoltage, cVoltage, err := getMc().ReadVoltage(rtuCommUid, addr)
	if err != nil {
		panic(err)
	}
	mp.AVoltage = math.Round(aVoltage*100) / 100
	mp.BVoltage = math.Round(bVoltage*100) / 100
	mp.CVoltage = math.Round(cVoltage*100) / 100

	_, aElectricCurrent, bElectricCurrent, cElectricCurrent, err := getMc().ReadElectricCurrent(rtuCommUid, addr)
	if err != nil {
		panic(err)
	}
	mp.AElectricCurrent = math.Round(aElectricCurrent*100) / 100
	mp.BElectricCurrent = math.Round(bElectricCurrent*100) / 100
	mp.CElectricCurrent = math.Round(cElectricCurrent*100) / 100

	totalPower, aPower, bPower, cPower, err := getMc().ReadPower(rtuCommUid, addr)
	if err != nil {
		panic(err)
	}
	mp.TotalActivePower = math.Round(totalPower*100) / 100
	mp.APower = math.Round(aPower*100) / 100
	mp.BPower = math.Round(bPower*100) / 100
	mp.CPower = math.Round(cPower*100) / 100
	tf, af, bf, cf, err := getMc().ReadPowerFactor(rtuCommUid, addr)
	if err != nil {
		panic(err)
	}
	mp.TotalPowerFactor = math.Round(tf*1000) / 1000
	mp.APowerFactor = math.Round(af*100) / 100
	mp.BPowerFactor = math.Round(bf*100) / 100
	mp.CPowerFactor = math.Round(cf*100) / 100
	if mp.TotalPowerFactor >= 1 {
		mp.TotalPowerFactor = 0.999
	}
	rpc.WriteResult(mp)
}

func getMsgAddress(rpc towgo.JsonRpcConnection) {
	var p struct {
		CommUid string `json:"comm_uid"`
	}
	rpc.ReadParams(&p)
	addr, err := getMc().ReadMsgAddr(p.CommUid, getMeterAddr(p.CommUid))
	if err != nil {
		panic(err)
	}
	rpc.WriteResult(fmt.Sprintf("0x%X", addr))
}

// 获取日冻结时间
func getDailyFreezingTime(rpc towgo.JsonRpcConnection) {
	var p struct {
		CommUid string `json:"comm_uid"`
	}
	rpc.ReadParams(&p)

	time, err := getMc().ReadDailyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
	if err != nil {
		panic(gerror.Wrap(err, "getDailyFreezingTime"))
	}

	rpc.WriteResult(time)

}
func geDeviceTime(rpc towgo.JsonRpcConnection) {
	var p struct {
		CommUid string `json:"comm_uid"`
	}
	rpc.ReadParams(&p)

	time, err := getMc().ReadTime(p.CommUid, getMeterAddr(p.CommUid))
	if err != nil {
		panic(gerror.Wrap(err, "geTime"))
	}
	rpc.WriteResult(time.Format("2006-01-02 15:04:05"))

}

func getReadMonthlyFreezingTime(rpc towgo.JsonRpcConnection) {
	var p struct {
		CommUid string `json:"comm_uid"`
	}
	rpc.ReadParams(&p)

	day, hour, err := getMc().ReadMonthlyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
	if err != nil {
		panic(gerror.Wrap(err, "getReadMonthlyFreezingTime"))
	}
	r := map[string]interface{}{}
	r["day"] = day
	r["hour"] = hour
	rpc.WriteResult(r)
}
func getFreezeTheData(rpc towgo.JsonRpcConnection) {
	var p struct {
		CommUid string `json:"comm_uid"`
	}
	rpc.ReadParams(&p)

	/*read, err := ADL400.H6000.Read(p.CommUid, getMeterAddr(p.CommUid))
	if err != nil {
		panic(err)
	}
	block, err := ParseHistoricalEnergyBlock(read)
	if err != nil {
		panic(err)
	}*/
	dayData := []*HistoricalEnergyBlock{}
	monthData := []*HistoricalEnergyBlock{}
	for i := 1; i <= 90; i++ {
		time.Sleep(10 * time.Second)

		address, err := ADL400.GetDailyBlockAddress(i)
		if err != nil {
			panic(err)
		}
		g.Log().Debugf("GetDailyBlockAddress:% X", address)
		read, err := address.Read(p.CommUid, getMeterAddr(p.CommUid))
		if err != nil {
			g.Log().Error(err)
			continue
		}
		block, err := ParseHistoricalEnergyBlock(read)
		if err != nil {
			panic(err)
		}
		dayData = append(dayData, block)
	}
	for i := 1; i <= 48; i++ {
		time.Sleep(10 * time.Second)
		address, err := ADL400.GetMonthlyBlockAddress(i)
		if err != nil {
			g.Log().Error(err)
			continue

		}
		g.Log().Debugf("GetMonthlyBlockAddress:% X", address)
		read, err := address.Read(p.CommUid, getMeterAddr(p.CommUid))
		if err != nil {
			g.Log().Error(err)
			continue
		}
		block, err := ParseHistoricalEnergyBlock(read)
		if err != nil {
			panic(err)
		}
		monthData = append(monthData, block)
	}
	r := map[string]interface{}{}
	r["day"] = dayData
	r["month"] = monthData
	rpc.WriteResult(r)
}

// HistoricalEnergyBlock 包含块读取的历史电能数据
type HistoricalEnergyBlock struct {
	FreezeTime            time.Time // 冻结时间
	TotalActiveEnergy     float64   // 总有功电能 (kWh)
	PeakActiveEnergy      float64   // 有功尖电能 (kWh)
	FlatActiveEnergy      float64   // 有功峰电能 (kWh)
	OffPeakActiveEnergy   float64   // 有功平电能 (kWh)
	ValleyActiveEnergy    float64   // 有功谷电能 (kWh)
	TotalReactiveEnergy   float64   // 总无功电能 (kvarh)
	PeakReactiveEnergy    float64   // 无功尖电能 (kvarh)
	FlatReactiveEnergy    float64   // 无功峰电能 (kvarh)
	OffPeakReactiveEnergy float64   // 无功平电能 (kvarh)
	ValleyReactiveEnergy  float64   // 无功谷电能 (kvarh)
	PhaseAActiveEnergy    float64   // A相正向有功电能 (kWh)
	PhaseBActiveEnergy    float64   // B相正向有功电能 (kWh)
	PhaseCActiveEnergy    float64   // C相正向有功电能 (kWh)
	MaxActiveDemand       float64   // 有功最大需量 (kW)
	MaxActiveDemandTime   time.Time // 有功最大需量发生时间
	MaxReactiveDemand     float64   // 无功最大需量 (kvar)
	MaxReactiveDemandTime time.Time // 无功最大需量发生时间
}

// parseUint16Time 解析寄存器中的时间格式
func parseUint16Time(register uint16) (byte, byte) {
	// 寄存器格式：高字节 = 第一部分，低字节 = 第二部分
	return byte(register >> 8), byte(register & 0xFF)
}

// parseEnergy 解析电能值 (32位数据：2个寄存器)
func parseEnergy(registers []uint16, offset int) float64 {
	value := uint32(registers[offset])<<16 | uint32(registers[offset+1])
	// 假设精度为0.01 kWh/kvarh (根据实际情况调整)
	return float64(value) * 0.01
}

// parseDemand 解析需量值 (16位数据)
func parseDemand(register uint16) float64 {
	// 假设精度为0.01 kW/kvar (根据实际情况调整)
	return float64(register) * 0.01
}

// parseDateTime 解析日期时间 (年、月、日、时、分)
func parseDateTime(year, month, day, hour, minute uint16) time.Time {
	// 处理特殊年份格式 (假设2000年基准)
	if year < 100 {
		year += 2000
	}

	// 注意：冻结日期可能不是当前日期
	return time.Date(
		int(year),
		time.Month(month),
		int(day),
		int(hour),
		int(minute),
		0, 0, time.Local,
	)
}

// ParseHistoricalEnergyBlock 解析 H6000 块读取的数据
func ParseHistoricalEnergyBlock(registers []uint16) (*HistoricalEnergyBlock, error) {
	// 验证数据长度应为 34个寄存器 * 2字节/寄存器 = 68字节
	if len(registers) != 34 {
		return nil, fmt.Errorf("invalid data length: expected 68 bytes, got %d", len(registers))
	}

	// 将字节数据转换为 uint16 寄存器数组
	/*	registers := make([]uint16, 34)
		err := binary.Read(bytes.NewReader(data), binary.BigEndian, &registers)
		if err != nil {
			return nil, fmt.Errorf("binary read error: %v", err)
		}*/

	block := &HistoricalEnergyBlock{}

	// 解析冻结时间
	freezeYear, freezeMonth := parseUint16Time(registers[0]) // 6000H: 年-月
	freezeDay, freezeHour := parseUint16Time(registers[1])   // 6001H: 日-时
	block.FreezeTime = parseDateTime(
		uint16(freezeYear), uint16(freezeMonth),
		uint16(freezeDay), uint16(freezeHour), 0,
	)

	// 解析电能数据 (32位值, 各2个寄存器)
	block.TotalActiveEnergy = parseEnergy(registers, 2)   // 6002H-6003H
	block.PeakActiveEnergy = parseEnergy(registers, 4)    // 6004H-6005H
	block.FlatActiveEnergy = parseEnergy(registers, 6)    // 6006H-6007H (峰)
	block.OffPeakActiveEnergy = parseEnergy(registers, 8) // 6008H-6009H (平)
	block.ValleyActiveEnergy = parseEnergy(registers, 10) // 600AH-600BH (谷)

	block.TotalReactiveEnergy = parseEnergy(registers, 12)   // 600CH-600DH
	block.PeakReactiveEnergy = parseEnergy(registers, 14)    // 600EH-600FH
	block.FlatReactiveEnergy = parseEnergy(registers, 16)    // 6010H-6011H (峰)
	block.OffPeakReactiveEnergy = parseEnergy(registers, 18) // 6012H-6013H (平)
	block.ValleyReactiveEnergy = parseEnergy(registers, 20)  // 6014H-6015H (谷)

	block.PhaseAActiveEnergy = parseEnergy(registers, 22) // 6016H-6017H
	block.PhaseBActiveEnergy = parseEnergy(registers, 24) // 6018H-6019H
	block.PhaseCActiveEnergy = parseEnergy(registers, 26) // 601AH-601BH

	// 解析有功最大需量及时间
	block.MaxActiveDemand = parseDemand(registers[28]) // 601CH (有功最大需量)

	minute, hour := parseUint16Time(registers[29]) // 601DH: 分-时
	day, month := parseUint16Time(registers[30])   // 601EH: 日-月
	block.MaxActiveDemandTime = parseDateTime(
		uint16(block.FreezeTime.Year()), uint16(month),
		uint16(day), uint16(hour), uint16(minute),
	)

	// 解析无功最大需量及时间
	block.MaxReactiveDemand = parseDemand(registers[31]) // 601FH (无功最大需量)

	minute, hour = parseUint16Time(registers[32]) // 6020H: 分-时
	day, month = parseUint16Time(registers[33])   // 6021H: 日-月
	block.MaxReactiveDemandTime = parseDateTime(
		uint16(block.FreezeTime.Year()), uint16(month),
		uint16(day), uint16(hour), uint16(minute),
	)

	return block, nil
}
