package service

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"be.ems/src/framework/i18n"
	"be.ems/src/framework/logger"
	"be.ems/src/framework/utils/date"
	"be.ems/src/framework/utils/file"
	"be.ems/src/framework/utils/parse"
	"be.ems/src/modules/ne_data/model"
	"be.ems/src/modules/ne_data/repository"
	sysService "be.ems/src/modules/system/service"
)

// 实例化数据层 CDREvent 结构体
var NewCDREvent = &CDREvent{
	cdrEventRepository: repository.NewCDREvent,
}

// CDREvent CDR会话事件 服务层处理
type CDREvent struct {
	cdrEventRepository *repository.CDREvent // CDR会话事件数据信息
}

// FindByPage 根据条件分页查询
func (r CDREvent) FindByPage(neType string, query map[string]string) ([]model.CDREvent, int64) {
	return r.cdrEventRepository.SelectByPage(neType, query)
}

// DeleteByIds 批量删除信息
func (r CDREvent) DeleteByIds(neType string, ids []int64) (int64, error) {
	// 检查是否存在
	rows := r.cdrEventRepository.SelectByIds(neType, ids)
	if len(rows) <= 0 {
		return 0, fmt.Errorf("not data")
	}

	if len(rows) == len(ids) {
		rows := r.cdrEventRepository.DeleteByIds(neType, ids)
		return rows, nil
	}
	// 删除信息失败！
	return 0, fmt.Errorf("delete fail")
}

// Insert 新增信息
func (s CDREvent) Insert(param model.CDREvent) int64 {
	return s.cdrEventRepository.Insert(param)
}

// ExportSMSC 导出数据到 xlsx 文件
func (r CDREvent) ExportSMSC(rows []model.CDREvent, fileName, language string) (string, error) {
	// 第一行表头标题
	headerCells := map[string]string{
		"A1": "ID",
		"B1": "NE Name",
		"C1": "Record Behavior",
		"D1": "Service Type",
		"E1": "Caller",
		"F1": "Called",
		"G1": "Result Code",
		"H1": "Result Cause",
		"I1": "Time",
	}
	// 读取字典数据 CDR 原因码
	dictCDRSMSCCauseCode := sysService.NewSysDictData.FindByType("cdr_cause_smsc")
	// 从第二行开始的数据
	dataCells := make([]map[string]any, 0)
	for i, row := range rows {
		idx := strconv.Itoa(i + 2)
		// 解析 JSON 字符串为 map
		var cdrJSON map[string]interface{}
		err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON)
		if err != nil {
			logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
			continue
		}
		// 记录类型
		recordType := ""
		if v, ok := cdrJSON["recordType"]; ok && v != nil {
			recordType = v.(string)
		}
		// 服务类型
		serviceType := ""
		if v, ok := cdrJSON["serviceType"]; ok && v != nil {
			serviceType = v.(string)
		}
		// 被叫
		called := ""
		if v, ok := cdrJSON["calledParty"]; ok && v != nil {
			called = v.(string)
		}
		// 主叫
		caller := ""
		if v, ok := cdrJSON["callerParty"]; ok && v != nil {
			caller = v.(string)
		}
		// 呼叫结果 0失败，1成功
		callResult := "FAILED"
		if v, ok := cdrJSON["result"]; ok && v != nil {
			resultVal := parse.Number(v)
			if resultVal == 1 {
				callResult = "SUCCESS"
			}
		}
		// 结果原因
		callCause := "UNKNOW ERROR"
		if v, ok := cdrJSON["cause"]; ok && v != nil {
			cause := fmt.Sprint(v)
			for _, v := range dictCDRSMSCCauseCode {
				if cause == v.DataValue {
					callCause = i18n.TKey(language, v.DataLabel)
					break
				}
			}
		}
		// 取时间
		timeStr := ""
		if v, ok := cdrJSON["updateTime"]; ok && v != nil {
			if releaseTime := parse.Number(v); releaseTime > 0 {
				timeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DDTHH_MM_SSZ)
			} else {
				timeStr = v.(string)
			}
		}

		dataCells = append(dataCells, map[string]any{
			"A" + idx: row.ID,
			"B" + idx: row.NeName,
			"C" + idx: recordType,
			"D" + idx: serviceType,
			"E" + idx: caller,
			"F" + idx: called,
			"G" + idx: callResult,
			"H" + idx: callCause,
			"I" + idx: timeStr,
		})
	}

	// 导出数据表格
	return file.WriteSheet(headerCells, dataCells, fileName, "")
}

// ExportSMF 导出数据到 xlsx 文件
func (r CDREvent) ExportSMF(rows []model.CDREvent, fileName string) (string, error) {
	// 第一行表头标题
	headerCells := map[string]string{
		"A1": "ID",
		"B1": "Charging ID",
		"C1": "NE Name",
		"D1": "Resource Unique ID",
		"E1": "Subscriber ID Data",
		"F1": "Subscriber ID Type",
		"G1": "Data Volume Uplink",
		"H1": "Data Volume Downlink",
		"I1": "Data Total Volume",
		"J1": "Duration",
		"K1": "Invocation Time",
		"L1": "User Identifier",
		"M1": "SSC Mode",
		"N1": "DNN ID",
		"O1": "PDU Type",
		"P1": "RAT Type",
		"Q1": "PDU IPv4 Address",
		"R1": "Network Function IPv4",
		"S1": "PDU IPv6 Address Swith Prefix",
		"T1": "Record Network Function ID",
		"U1": "Record Type",
		"V1": "Record Opening Time",
	}
	// 从第二行开始的数据
	dataCells := make([]map[string]any, 0)
	for i, row := range rows {
		idx := strconv.Itoa(i + 2)
		// 解析 JSON 字符串为 map
		var cdrJSON map[string]interface{}
		err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON)
		if err != nil {
			logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
			continue
		}
		// 计费ID
		chargingID := ""
		if v, ok := cdrJSON["chargingID"]; ok && v != nil {
			chargingID = fmt.Sprint(parse.Number(v))
		}
		// 订阅 ID 类型
		subscriptionIDType := "-"
		// 订阅 ID 数据
		subscriptionIDData := "-"
		if v, ok := cdrJSON["subscriberIdentifier"]; ok && v != nil {
			if sub, subOk := v.(map[string]any); subOk && sub != nil {
				subscriptionIDType = sub["subscriptionIDType"].(string)
				subscriptionIDData = sub["subscriptionIDData"].(string)
			}
		}

		// 网络功能 IPv4 地址
		networkFunctionIPv4Address := ""
		if v, ok := cdrJSON["nFunctionConsumerInformation"]; ok && v != nil {
			if conInfo, conInfoOk := v.(map[string]any); conInfoOk && conInfo != nil {
				networkFunctionIPv4Address = conInfo["networkFunctionIPv4Address"].(string)
			}
		}

		// 数据量上行链路
		var dataVolumeUplink int64 = 0
		// 数据量下行链路
		var dataVolumeDownlink int64 = 0
		// 数据总量
		var dataTotalVolume int64 = 0
		if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil {
			usageList := v.([]any)
			if len(usageList) > 0 {
				for _, used := range usageList {
					usedUnit := used.(map[string]any)
					usedUnitList := usedUnit["usedUnitContainer"].([]any)
					if len(usedUnitList) > 0 {
						for _, data := range usedUnitList {
							udata := data.(map[string]any)
							if dup, dupOk := udata["dataVolumeUplink"]; dupOk {
								dataVolumeUplink += parse.Number(dup)
							}
							if ddown, ddownOk := udata["dataVolumeDownlink"]; ddownOk {
								dataVolumeDownlink += parse.Number(ddown)
							}
							if dt, dtOk := udata["dataTotalVolume"]; dtOk {
								dataTotalVolume += parse.Number(dt)
							}
						}
					}
				}
			}
		}
		// 时长
		duration := "-"
		if v, ok := cdrJSON["duration"]; ok && v != nil {
			duration = fmt.Sprint(parse.Number(v))
		}
		// 调用时间
		invocationTimestamp := ""
		if v, ok := cdrJSON["invocationTimestamp"]; ok && v != nil {
			invocationTimestamp = v.(string)
		}
		// 记录打开时间
		User_Identifier := ""
		SSC_Mode := ""
		RAT_Type := ""
		DNN_ID := ""
		PDU_Type := ""
		PDU_IPv4 := ""
		PDU_IPv6 := ""
		if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil {
			pduInfo := v.(map[string]any)

			if v, ok := pduInfo["userIdentifier"]; ok && v != nil {
				User_Identifier = v.(string)
			}
			if v, ok := pduInfo["sSCMode"]; ok && v != nil {
				SSC_Mode = v.(string)
			}
			if v, ok := pduInfo["rATType"]; ok && v != nil {
				RAT_Type = v.(string)
			}
			if v, ok := pduInfo["dNNID"]; ok && v != nil {
				DNN_ID = v.(string)
			}
			if v, ok := pduInfo["pDUType"]; ok && v != nil {
				PDU_Type = v.(string)
			}
			if v, ok := pduInfo["pDUAddress"]; ok && v != nil {
				pDUAddress := v.(map[string]any)
				if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil {
					PDU_IPv4 = addr.(string)
				}
				if addr, ok := pDUAddress["pDUIPv6AddresswithPrefix"]; ok && addr != nil {
					PDU_IPv6 = addr.(string)
				}
			}
		}

		// 记录网络参数ID
		recordNFID := ""
		if v, ok := cdrJSON["recordingNetworkFunctionID"]; ok && v != nil {
			recordNFID = v.(string)
		}

		//记录开始时间
		recordOpeningTime := ""
		if v, ok := cdrJSON["recordOpeningTime"]; ok && v != nil {
			recordOpeningTime = v.(string)
		}

		//记录类型
		recordType := ""
		if v, ok := cdrJSON["recordType"]; ok && v != nil {
			recordType = v.(string)
		}

		dataCells = append(dataCells, map[string]any{
			"A" + idx: row.ID,
			"B" + idx: chargingID,
			"C" + idx: row.NeName,
			"D" + idx: row.RmUid,
			"E" + idx: subscriptionIDData,
			"F" + idx: subscriptionIDType,
			"G" + idx: dataVolumeUplink,
			"H" + idx: dataVolumeDownlink,
			"I" + idx: dataTotalVolume,
			"J" + idx: duration,
			"K" + idx: invocationTimestamp,
			"L" + idx: User_Identifier,
			"M" + idx: SSC_Mode,
			"N" + idx: DNN_ID,
			"O" + idx: PDU_Type,
			"P" + idx: RAT_Type,
			"Q" + idx: PDU_IPv4,
			"R" + idx: networkFunctionIPv4Address,
			"S" + idx: PDU_IPv6,
			"T" + idx: recordNFID,
			"U" + idx: recordType,
			"V" + idx: recordOpeningTime,
		})
	}

	// 导出数据表格
	return file.WriteSheet(headerCells, dataCells, fileName, "")
}

// ExportSGWC 导出数据到 xlsx 文件
func (r CDREvent) ExportSGWC(rows []model.CDREvent, fileName string) (string, error) {
	// 第一行表头标题
	headerCells := map[string]string{
		"A1": "ID",
		"B1": "NE Name",
		"C1": "Resource Unique ID",
		"D1": "Charging ID",
		"E1": "IMSI",
		"F1": "MSISDN",
		"G1": "GPRS Uplink",
		"H1": "GPRS Downlink",
		"I1": "Duration",
		"J1": "Invocation Time",
		"K1": "PGW Address",
		"L1": "SGW Address",
		"M1": "RAT Type",
		"N1": "PDPPDN Type",
		"O1": "PDPPDN Address",
		"P1": "Node Address",
		"Q1": "Node Type",
		"R1": "Record Access Point Name NI",
		"S1": "Record Cause For Rec Closing",
		"T1": "Record Sequence Number",
		"U1": "Local Record Sequence Number",
		"V1": "Record Type",
		"W1": "Record Opening Time",
	}
	// 从第二行开始的数据
	dataCells := make([]map[string]any, 0)
	for i, row := range rows {
		idx := strconv.Itoa(i + 2)
		// 解析 JSON 字符串为 map
		var cdrJSON map[string]interface{}
		err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON)
		if err != nil {
			logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
			continue
		}
		// 计费ID
		chargingID := ""
		if v, ok := cdrJSON["chargingID"]; ok && v != nil {
			chargingID = fmt.Sprint(parse.Number(v))
		}
		// IMSI
		servedIMSI := ""
		if v, ok := cdrJSON["servedIMSI"]; ok && v != nil {
			servedIMSI = fmt.Sprint(v)
		}
		// MSISDN
		servedMSISDN := ""
		if v, ok := cdrJSON["servedMSISDN"]; ok && v != nil {
			servedMSISDN = fmt.Sprint(v)
		}
		// pGWAddressUsed
		pGWAddressUsed := ""
		if v, ok := cdrJSON["pGWAddressUsed"]; ok && v != nil {
			pGWAddressUsed = fmt.Sprint(v)
			headerCells["K1"] = "PGW Address"
		}
		if v, ok := cdrJSON["GGSNAddress"]; ok && v != nil {
			pGWAddressUsed = fmt.Sprint(v)
			headerCells["K1"] = "GGSN Address"
		}
		// sGWAddress
		sGWAddress := ""
		if v, ok := cdrJSON["sGWAddress"]; ok && v != nil {
			sGWAddress = fmt.Sprint(v)
			headerCells["L1"] = "SGW Address"
		}
		if v, ok := cdrJSON["SGSNAddress"]; ok && v != nil {
			sGWAddress = fmt.Sprint(v)
			headerCells["L1"] = "SGSN Address"
		}
		// recordType
		recordType := ""
		if v, ok := cdrJSON["recordType"]; ok && v != nil {
			recordType = fmt.Sprint(v)
		}
		// rATType
		rATType := ""
		if v, ok := cdrJSON["rATType"]; ok && v != nil {
			rATType = fmt.Sprint(v)
		}
		// pdpPDNType
		pdpPDNType := ""
		if v, ok := cdrJSON["pdpPDNType"]; ok && v != nil {
			pdpPDNType = fmt.Sprint(v)
		}
		// servedPDPPDNAddress
		servedPDPPDNAddress := ""
		if v, ok := cdrJSON["servedPDPPDNAddress"]; ok && v != nil {
			servedPDPPDNAddress = fmt.Sprint(v)
		}
		// servedPDPPDNAddress
		servingNodeAddress := []string{}
		if v, ok := cdrJSON["servingNodeAddress"]; ok && v != nil {
			for _, v := range v.([]any) {
				servingNodeAddress = append(servingNodeAddress, fmt.Sprint(v))
			}
		}
		// servingNodeType
		servingNodeType := []string{}
		if v, ok := cdrJSON["servingNodeType"]; ok && v != nil {
			for _, v := range v.([]any) {
				if v, ok := v.(map[string]any)["servingNodeType"]; ok && v != nil {
					servingNodeType = append(servingNodeType, fmt.Sprint(v))
				}
			}
		}
		// accessPointNameNI
		accessPointNameNI := ""
		if v, ok := cdrJSON["accessPointNameNI"]; ok && v != nil {
			accessPointNameNI = fmt.Sprint(v)
		}
		// causeForRecClosing
		causeForRecClosing := ""
		if v, ok := cdrJSON["causeForRecClosing"]; ok && v != nil {
			causeForRecClosing = fmt.Sprint(v)
		}
		// recordSequenceNumber
		recordSequenceNumber := ""
		if v, ok := cdrJSON["recordSequenceNumber"]; ok && v != nil {
			recordSequenceNumber = fmt.Sprint(v)
		}
		// localRecordSequenceNumber
		localRecordSequenceNumber := ""
		if v, ok := cdrJSON["localRecordSequenceNumber"]; ok && v != nil {
			localRecordSequenceNumber = fmt.Sprint(v)
		}
		// 数据量上行链路
		var dataVolumeGPRSUplink int64 = 0
		// 数据量下行链路
		var dataVolumeGPRSDownlink int64 = 0
		if v, ok := cdrJSON["listOfTrafficVolumes"]; ok && v != nil {
			usageList := v.([]any)
			if len(usageList) > 0 {
				for _, used := range usageList {
					usedUnit := used.(map[string]any)
					if dup, dupOk := usedUnit["dataVolumeGPRSUplink"]; dupOk {
						dataVolumeGPRSUplink = parse.Number(dup)
					}
					if ddown, ddownOk := usedUnit["dataVolumeGPRSDownlink"]; ddownOk {
						dataVolumeGPRSDownlink = parse.Number(ddown)
					}
				}
			}
		}
		// 时长
		duration := "-"
		if v, ok := cdrJSON["duration"]; ok && v != nil {
			duration = fmt.Sprint(parse.Number(v))
		}
		// 调用时间
		invocationTimestamp := ""
		if v, ok := cdrJSON["recordOpeningTime"]; ok && v != nil {
			invocationTimestamp = v.(string)
		}

		dataCells = append(dataCells, map[string]any{
			"A" + idx: row.ID,
			"B" + idx: row.NeName,
			"C" + idx: row.RmUid,
			"D" + idx: chargingID,
			"E" + idx: servedIMSI,
			"F" + idx: servedMSISDN,
			"G" + idx: dataVolumeGPRSUplink,
			"H" + idx: dataVolumeGPRSDownlink,
			"I" + idx: duration,
			"J" + idx: invocationTimestamp,
			"K" + idx: pGWAddressUsed,
			"L" + idx: sGWAddress,
			"M" + idx: rATType,
			"N" + idx: pdpPDNType,
			"O" + idx: servedPDPPDNAddress,
			"P" + idx: strings.Join(servingNodeAddress, ","),
			"Q" + idx: strings.Join(servingNodeType, ","),
			"R" + idx: accessPointNameNI,
			"S" + idx: causeForRecClosing,
			"T" + idx: recordSequenceNumber,
			"U" + idx: localRecordSequenceNumber,
			"V" + idx: recordType,
			"W" + idx: invocationTimestamp,
		})
	}

	// 导出数据表格
	return file.WriteSheet(headerCells, dataCells, fileName, "")
}

// ExportIMS 导出数据到 xlsx 文件
func (r CDREvent) ExportIMS(rows []model.CDREvent, fileName, language string) (string, error) {
	// 第一行表头标题
	headerCells := map[string]string{
		"A1": "ID",
		"B1": "NE Name",
		"C1": "Record Behavior",
		"D1": "Type",
		"E1": "Caller",
		"F1": "Called",
		"G1": "Duration",
		"H1": "Result Code",
		"I1": "Result Cause",
		"J1": "Call Start Time",
		"K1": "Hangup Time",
	}
	// 读取字典数据 CDR SIP响应代码类别类型
	dictCDRSipCode := sysService.NewSysDictData.FindByType("cdr_sip_code")
	// 读取字典数据 CDR SIP响应代码类别类型原因
	dictCDRSipCodeCause := sysService.NewSysDictData.FindByType("cdr_sip_code_cause")
	// 读取字典数据 CDR 呼叫类型
	dictCDRCallType := sysService.NewSysDictData.FindByType("cdr_call_type")
	// 从第二行开始的数据
	dataCells := make([]map[string]any, 0)
	for i, row := range rows {
		idx := strconv.Itoa(i + 2)
		// 解析 JSON 字符串为 map
		var cdrJSON map[string]any
		err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON)
		if err != nil {
			logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
			continue
		}
		// 记录类型
		recordType := ""
		if v, ok := cdrJSON["recordType"]; ok && v != nil {
			recordType = v.(string)
		}
		// 呼叫类型
		callType := "sms"
		callTypeLable := "SMS"
		if v, ok := cdrJSON["callType"]; ok && v != nil {
			callType = v.(string)
			for _, v := range dictCDRCallType {
				if callType == v.DataValue {
					callTypeLable = i18n.TKey(language, v.DataLabel)
					break
				}
			}
		}
		// 被叫
		called := ""
		if v, ok := cdrJSON["calledParty"]; ok && v != nil {
			called = v.(string)
		}
		// 主叫
		caller := ""
		if v, ok := cdrJSON["callerParty"]; ok && v != nil {
			caller = v.(string)
		}
		// 时长
		duration := "-"
		if v, ok := cdrJSON["callDuration"]; ok && v != nil && callType != "sms" {
			duration = fmt.Sprintf("%ds", parse.Number(v))
		}
		// 呼叫结果 非短信都有code作为结果 sms短信都ok
		callResult := "Other"
		callCause := "Call failure for other reason"
		if callType == "sms" {
			callResult = "Success"
			callCause = "Normal Send"
		} else {
			if v, ok := cdrJSON["cause"]; ok && v != nil {
				cause := fmt.Sprint(v)
				for _, v := range dictCDRSipCode {
					if cause == v.DataValue {
						callResult = i18n.TKey(language, v.DataLabel)
						break
					}
				}
				for _, v := range dictCDRSipCodeCause {
					if cause == v.DataValue {
						callCause = i18n.TKey(language, v.DataLabel)
						break
					}
				}
			}
		}
		// 呼叫时间
		seizureTimeStr := ""
		if v, ok := cdrJSON["seizureTime"]; ok && v != nil {
			if seizureTime := parse.Number(v); seizureTime > 0 {
				seizureTimeStr = date.ParseDateToStr(seizureTime, date.YYYY_MM_DDTHH_MM_SSZ)
			} else {
				seizureTimeStr = v.(string)
			}
		}
		// 挂断时间
		releaseTimeStr := ""
		if v, ok := cdrJSON["releaseTime"]; ok && v != nil {
			if releaseTime := parse.Number(v); releaseTime > 0 {
				releaseTimeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DDTHH_MM_SSZ)
			} else {
				releaseTimeStr = v.(string)
			}
		}

		dataCells = append(dataCells, map[string]any{
			"A" + idx: row.ID,
			"B" + idx: row.NeName,
			"C" + idx: recordType,
			"D" + idx: callTypeLable,
			"E" + idx: caller,
			"F" + idx: called,
			"G" + idx: duration,
			"H" + idx: callResult,
			"I" + idx: callCause,
			"J" + idx: seizureTimeStr,
			"K" + idx: releaseTimeStr,
		})
	}

	// 导出数据表格
	return file.WriteSheet(headerCells, dataCells, fileName, "")
}

// IMSCDRMOSHour CDR MOS 统计
func (r CDREvent) IMSCDRMOSHour(rmUID string, timestamp int64) []map[string]any {
	t := time.UnixMilli(timestamp)
	beginTime := t
	endTime := t
	// 检查时分秒是否都为零
	if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 {
		// 获取当天起始时间（00:00:00）
		beginTime = t.Truncate(time.Hour)
		// 计算当天结束时间（23:59:59）
		endTime = beginTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
	} else {
		// 起始时间：当前小时的 00 分 00 秒
		beginTime = t.Truncate(time.Hour)
		// 结束时间：当前小时的 59 分 59 秒 999 毫秒
		endTime = beginTime.Add(time.Hour - time.Millisecond)
	}

	query := map[string]string{
		"rmUID":      rmUID,
		"recordType": "MOC",
		"beginTime":  fmt.Sprintf("%d", beginTime.Unix()),
		"endTime":    fmt.Sprintf("%d", endTime.Unix()),
	}
	rows, total := r.cdrEventRepository.SelectByPage("IMS", query)
	if total == 0 {
		return []map[string]any{}
	}
	// 创建一个map来存储按时间段合并后的数据
	timeGroup := make(map[int64]map[string]float64)
	// 遍历每个数据项
	for _, row := range rows {
		// 将毫秒时间戳转换为小时级时间戳（保留到小时的起始毫秒）
		timeHour := row.Timestamp / 3600 * 3600 // 1小时 = 3600000毫秒

		// 解析 JSON 字符串为 map
		var cdrJSON map[string]interface{}
		err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON)
		if err != nil {
			logger.Warnf("Unmarshal JSON: %s", err.Error())
			continue
		}

		// 记录类型
		var mosAverage float64 = 0
		if v, ok := cdrJSON["mosAverage"]; ok && v != nil {
			mosAverage = v.(float64)
		} else {
			continue
		}

		// 合并到对应的小时段
		if _, exists := timeGroup[timeHour]; !exists {
			timeGroup[timeHour] = map[string]float64{
				"total":  0,
				"mosSum": 0,
			}
		}
		timeGroup[timeHour]["total"] += 1
		timeGroup[timeHour]["mosSum"] += mosAverage
	}

	// 时间组合输出
	data := make([]map[string]any, 0, len(timeGroup))
	for hour, sums := range timeGroup {
		data = append(data, map[string]any{
			"timeGroup": fmt.Sprintf("%d", hour),
			"total":     sums["total"],
			"mosSum":    float64(int(sums["mosSum"]*100)) / 100,
			"mosAvg":    float64(int(sums["mosSum"]/sums["total"]*100)) / 100,
		})
	}
	return data
}

// IMSCDRCCTHour CDR CCT 统计
func (r CDREvent) IMSCDRCCTHour(rmUID string, timestamp int64) []map[string]any {
	t := time.UnixMilli(timestamp)
	beginTime := t
	endTime := t
	// 检查时分秒是否都为零
	if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 {
		// 获取当天起始时间（00:00:00）
		beginTime = t.Truncate(time.Hour)
		// 计算当天结束时间（23:59:59）
		endTime = beginTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
	} else {
		// 起始时间：当前小时的 00 分 00 秒
		beginTime = t.Truncate(time.Hour)
		// 结束时间：当前小时的 59 分 59 秒 999 毫秒
		endTime = beginTime.Add(time.Hour - time.Millisecond)
	}

	query := map[string]string{
		"rmUID":      rmUID,
		"recordType": "MOC",
		"beginTime":  fmt.Sprintf("%d", beginTime.Unix()),
		"endTime":    fmt.Sprintf("%d", endTime.Unix()),
	}
	rows, total := r.cdrEventRepository.SelectByPage("IMS", query)
	if total == 0 {
		return []map[string]any{}
	}
	// 创建一个map来存储按时间段合并后的数据
	timeGroup := make(map[int64]map[string]float64)
	// 遍历每个数据项
	for _, row := range rows {
		// 将毫秒时间戳转换为小时级时间戳（保留到小时的起始毫秒）
		timeHour := row.Timestamp / 3600 * 3600 // 1小时 = 3600000毫秒

		// 解析 JSON 字符串为 map
		var cdrJSON map[string]interface{}
		err := json.Unmarshal([]byte(row.CdrJson), &cdrJSON)
		if err != nil {
			logger.Warnf("Unmarshal JSON: %s", err.Error())
			continue
		}

		// 记录类型
		var callConnectionTime float64 = 0
		if v, ok := cdrJSON["callConnectionTime"]; ok && v != nil {
			callConnectionTime = v.(float64)
		} else {
			continue
		}

		// 合并到对应的小时段
		if _, exists := timeGroup[timeHour]; !exists {
			timeGroup[timeHour] = map[string]float64{
				"total":  0,
				"cctSum": 0,
			}
		}
		timeGroup[timeHour]["total"] += 1
		timeGroup[timeHour]["cctSum"] += callConnectionTime
	}

	// 时间组合输出
	data := make([]map[string]any, 0, len(timeGroup))
	for hour, sums := range timeGroup {
		data = append(data, map[string]any{
			"timeGroup": fmt.Sprintf("%d", hour),
			"total":     sums["total"],
			"cctSum":    float64(int(sums["cctSum"]*100)) / 100,
			"cctAvg":    float64(int(sums["cctSum"]/sums["total"]*100)) / 100,
		})
	}
	return data
}
