package service

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

	"be.ems/src/framework/logger"
	"be.ems/src/framework/utils/file"
	"be.ems/src/framework/utils/parse"
	"be.ems/src/modules/network_data/model"
	"be.ems/src/modules/network_data/repository"
)

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

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

// SelectPage 根据条件分页查询
func (r *CDREventSGWC) SelectPage(querys model.CDREventSGWCQuery) ([]model.CDREventSGWC, int64) {
	return r.cdrEventRepository.SelectByPage(querys)
}

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

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

// ExportXlsx 导出数据到 xlsx 文件
func (r CDREventSGWC) ExportXlsx(rows []model.CDREventSGWC, 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.CDRJSONStr), &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, "")
}
