package reporter

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	modem "hnyfkj.com.cn/rtu/bxs-sy/air720u"
	"hnyfkj.com.cn/rtu/bxs-sy/baseapp"
	mcu "hnyfkj.com.cn/rtu/bxs-sy/mcu_ctrl_board"
)

type StrEnv struct {
	Timestamp   string `json:"timestamp"`   // 时间戳(秒, 存在"​​2038-01-19 03:14:07 UTC​​"溢出风险)
	Temperature string `json:"temperature"` // 温度(0.1°C)
	Humidity    string `json:"humidity"`    // 湿度(0.1%)
	Illuminance string `json:"illuminance"` // 照度(0.1 Lux)
	Voltage     string `json:"voltage"`     // 电压(0.1V)
}

func LoopRecvEnvDataGrp(ctx context.Context) {
	for {
		select {
		case grpData := <-mcu.Board.EnvDataGrpCh:
			// 1, 已经读取环境数据
			mcu.MCBSetEnvStateBit(mcu.ParsingEnvData)
			strEnvGrp := make([]StrEnv, len(grpData))
			for idx, envData := range grpData {
				strEnvGrp[idx].Timestamp, strEnvGrp[idx].Temperature, strEnvGrp[idx].Humidity,
					strEnvGrp[idx].Illuminance, strEnvGrp[idx].Voltage = envData.StringWithoutUnit()
				baseapp.Logger.Infof("[%s] 收到一组环境数据: [%02d]: %s", MODULE_NAME, idx+1, envData.LogString())
			}

			// 2, 上报到后端服务器
			if !Reporter.IsLogin() {
				baseapp.Logger.Warnf("[%s] 未登录, 无法上报环境数据!", MODULE_NAME)
				mcu.MCBSetEnvStateBit(mcu.Idle)
				continue
			}

			mcu.MCBSetEnvStateBit(mcu.EnvDataUploading)
			now := time.Now()
			baseapp.Logger.Infof("[%s] 正在上报环境数据到服务器...", MODULE_NAME)

			type notify struct {
				IMEI       string   `json:"imei"`
				EnvDataGrp []StrEnv `json:"envDataGroup"`
			}

			notifyVar := notify{
				IMEI:       modem.GetIMEI(),
				EnvDataGrp: strEnvGrp,
			}

			notifyBytes, err := json.Marshal(notifyVar)
			if err != nil {
				baseapp.Logger.Errorf("[%s] 上报环境数据到服务器失败: %v!!", MODULE_NAME, err)
				mcu.MCBSetEnvStateBit(mcu.Idle)
				continue
			}

			topic := fmt.Sprintf("/yfkj/bxs-sy/notify/%s/envData24h", Reporter.dui)
			token := Reporter.client.Publish(topic, Reporter.msgQos, false, notifyBytes)
			select {
			case <-ctx.Done():
				return
			case <-token.Done():
			}

			if token.Error() != nil {
				baseapp.Logger.Errorf("[%s] 上报环境数据到服务器失败: %v!!", MODULE_NAME, token.Error())
				mcu.MCBSetEnvStateBit(mcu.Idle)
				continue
			}

			elapsed := time.Since(now).Milliseconds()

			// 3, 上报服务器已完成
			baseapp.Logger.Infof("[%s] 上报环境数据到服务器成功完成, 用时: %d毫秒", MODULE_NAME, elapsed)
			mcu.MCBSetEnvStateBit(mcu.Idle)
		case <-ctx.Done():
			return
		}
	}
}

func LoopRecvEnvDataOne(ctx context.Context) {
	for {
		select {
		case envData := <-mcu.Board.EnvDataOneCh:
			// 1, 已经读取环境数据
			mcu.MCBSetEnvStateBit(mcu.ParsingEnvData)
			var strEnv StrEnv
			strEnv.Timestamp, strEnv.Temperature, strEnv.Humidity,
				strEnv.Illuminance, strEnv.Voltage = envData.StringWithoutUnit()
			baseapp.Logger.Infof("[%s] 收到一条环境数据: %s", MODULE_NAME, envData.LogString())

			// 2, 上报到后端服务器
			if !Reporter.IsLogin() {
				baseapp.Logger.Warnf("[%s] 未登录, 无法上报环境数据!", MODULE_NAME)
				mcu.MCBSetEnvStateBit(mcu.Idle)
				continue
			}

			mcu.MCBSetEnvStateBit(mcu.EnvDataUploading)
			now := time.Now()
			baseapp.Logger.Infof("[%s] 正在上报环境数据到服务器...", MODULE_NAME)

			type notify struct {
				IMEI    string `json:"imei"`
				EnvData StrEnv `json:"envData"`
			}

			notifyVar := notify{
				IMEI:    modem.GetIMEI(),
				EnvData: strEnv,
			}

			notifyBytes, err := json.Marshal(notifyVar)
			if err != nil {
				baseapp.Logger.Errorf("[%s] 上报环境数据到服务器失败: %v!!", MODULE_NAME, err)
				mcu.MCBSetEnvStateBit(mcu.Idle)
				continue
			}

			topic := fmt.Sprintf("/yfkj/bxs-sy/notify/%s/envDataNow", Reporter.dui)
			token := Reporter.client.Publish(topic, Reporter.msgQos, false, notifyBytes)
			select {
			case <-ctx.Done():
				return
			case <-token.Done():
			}

			if token.Error() != nil {
				baseapp.Logger.Errorf("[%s] 上报环境数据到服务器失败: %v!!", MODULE_NAME, token.Error())
				mcu.MCBSetEnvStateBit(mcu.Idle)
				continue
			}

			elapsed := time.Since(now).Milliseconds()

			// 3, 上报服务器已完成
			mcu.MCBSetEnvStateBit(mcu.Idle)
			baseapp.Logger.Infof("[%s] 上报环境数据到服务器成功完成, 用时: %d毫秒", MODULE_NAME, elapsed)
		case <-ctx.Done():
			return
		}
	}
}
