package service

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"be.ems/src/framework/database/redis"
	"be.ems/src/framework/utils/date"
	neService "be.ems/src/modules/ne/service"
	"be.ems/src/modules/ne_data/model"
	"be.ems/src/modules/ne_data/repository"
)

// 实例化服务层 UDMSubUser 结构体
var NewUDMSubUser = &UDMSubUser{
	udmSubRepository:    repository.NewUDMSub,
	UDMExtendRepository: repository.NewUDMExtend,
}

// UDM签约信息 服务层处理
type UDMSubUser struct {
	udmSubRepository    *repository.UDMSubUser // UDM签约信息数据信息
	UDMExtendRepository *repository.UDMExtend  // UDM用户IMSI信息数据信息
}

// dataByRedis UDM签约用户 db:0 中 udm-sd:*
func (r *UDMSubUser) dataByRedis(imsi, neId string) []model.UDMSubUser {
	arr := []model.UDMSubUser{}
	key := fmt.Sprintf("udm-sd:%s", imsi)
	source := fmt.Sprintf("UDM_%s", neId)

	// 网元主机的Redis客户端
	redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId)
	if err != nil {
		return arr
	}
	defer func() {
		redisClient.Close()
		redis.ConnectPush(source, nil)
	}()
	redis.ConnectPush(source, redisClient.Client)

	udmsdArr, err := redis.GetKeys(source, key)
	if err != nil {
		return arr
	}
	mkv, err := redis.GetHashBatch(source, udmsdArr)
	if err != nil {
		return arr
	}

	for k, m := range mkv {
		if len(k) != 22 {
			continue
		}

		// 跳过-号数据 udm-sd:360000100000130
		imsi, hasPrefix := strings.CutPrefix(k, "udm-sd:")
		if strings.Contains(imsi, "-") || !hasPrefix {
			continue
		}
		var createTime int64 = 0
		if v, ok := m["create_time"]; ok {
			t := date.ParseStrToDate(v, date.YYYY_MM_DDTHH_MM_SSZ)
			createTime = t.UnixMilli()
		} else {
			createTime = time.Now().UnixMilli()
		}

		a := model.UDMSubUser{
			CreateTime: createTime,
			NeId:       neId,
			IMSI:       imsi,         // udm-sd:360000100000130
			MSISDN:     m["gpsi"],    // 8612300000130
			SmfSel:     m["smf-sel"], // def_snssai
			SmData:     m["sm-dat"],  // 1-000001&cmnet&ims&3gnet
			Cag:        m["cag"],     // def_cag
		}

		// def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,-
		if v, ok := m["am-dat"]; ok {
			arr := strings.Split(v, ",")
			a.AmDat = v
			a.UeAmbrTpl = arr[0]
			a.NssaiTpl = arr[1]
			a.RatRestrictions = arr[2]
			a.AreaForbiddenTpl = arr[3]
			a.ServiceAreaRestrictionTpl = arr[4]
			a.CnTypeRestrictions = arr[5]
			a.RfspIndex = arr[6]
			a.SubsRegTime = arr[7]
			a.UeUsageType = arr[8]
			a.ActiveTime = arr[9]
			a.MicoAllowed = "0" // arr[10]
			a.OdbPs = "1"       // arr[11]
			a.GroupId = "-"     // arr[12]
			if len(arr) > 10 {
				a.MicoAllowed = arr[10]
			}
			if len(arr) > 11 {
				a.OdbPs = arr[11]
			}
			if len(arr) > 12 && arr[12] != "-" {
				a.GroupId = arr[12]
			}
		}
		// 1,64,24,65,def_eps,1,2,010200000000,-
		if v, ok := m["eps-dat"]; ok {
			arr := strings.Split(v, ",")
			// 跳过非常规数据
			if len(arr) > 9 {
				continue
			}
			a.EpsDat = v
			a.EpsFlag = arr[0]
			a.EpsOdb = arr[1]
			a.HplmnOdb = arr[2]
			a.Ard = arr[3]
			a.Epstpl = arr[4]
			a.ContextId = arr[5]
			a.ApnNum = arr[6] // 导入和导出不用
			a.ApnContext = arr[7]
			if len(arr) >= 9 {
				a.StaticIp = arr[8]
			}
		}

		arr = append(arr, a)
	}
	return arr
}

// ResetData 重置鉴权用户数据，清空数据库重新同步Redis数据
func (r *UDMSubUser) ResetData(neId string) int64 {
	subArr := r.dataByRedis("*", neId)
	// 数据清空后添加
	go r.udmSubRepository.ClearAndInsert(neId, subArr)
	return int64(len(subArr))
}

// ParseInfo 解析单个用户imsi签约信息 data从命令MML得到的结果
func (r *UDMSubUser) ParseInfo(imsi, neId string, data map[string]string) model.UDMSubUser {
	u := r.udmSubRepository.SelectByIMSIAndNeID(imsi, neId)

	cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64) // 0x03(EPC|5GC)
	rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64)       // 0x00(VIRTUAL|WLAN|EUTRA|NR)
	msisdn := data["MSISDN"]
	if imsMsisdnLen := strings.Index(msisdn, ","); imsMsisdnLen != -1 {
		msisdn = msisdn[:imsMsisdnLen]
	}

	// 用于更新
	u.IMSI = imsi
	u.MSISDN = msisdn
	u.NeId = neId
	u.UeAmbrTpl = data["AMBR"]
	u.NssaiTpl = data["NSSAI"]
	u.AreaForbiddenTpl = data["AreaForbidden"]
	u.ServiceAreaRestrictionTpl = data["ServiceAreaRestriction"]
	u.CnTypeRestrictions = fmt.Sprint(cnType)
	u.RatRestrictions = fmt.Sprint(rat)
	u.MicoAllowed = data["MICO"]
	u.SmData = data["SM-Data(snssai+dnn[1..n])"]
	u.SmfSel = data["Smf-Selection"]
	u.Cag = data["cag"]

	// 1,64,24,65,def_eps,1,2,010200000000,-
	if v, ok := data["EPS-Data"]; ok {
		u.EpsDat = v
		arr := strings.Split(v, ",")
		u.EpsFlag = arr[0]
		u.EpsOdb = arr[1]
		u.HplmnOdb = arr[2]
		u.Ard = arr[3]
		u.Epstpl = arr[4]
		u.ContextId = arr[5]
		u.ApnNum = arr[6] // 导入和导出不用
		u.ApnContext = arr[7]
		u.StaticIp = arr[8]
	}

	// 补充用户拓展信息
	info := r.UDMExtendRepository.SelectByIMSIAndNeID(imsi, neId)
	if info.IMSI == imsi {
		u.Remark = info.Remark
	}
	return u
}

// FindByPage 分页查询数据库
func (r *UDMSubUser) FindByPage(query map[string]string) ([]model.UDMSubUser, int64) {
	return r.udmSubRepository.SelectPage(query)
}

// Find 查询数据库
func (r *UDMSubUser) Find(u model.UDMSubUser) []model.UDMSubUser {
	return r.udmSubRepository.SelectList(u)
}

// Insert 从数据中读取后删除imsi再存入数据库
// imsi长度15，ki长度32，opc长度0或者32
func (r *UDMSubUser) Insert(neId string, u model.UDMSubUser) int64 {
	uArr := r.dataByRedis(u.IMSI, neId)
	if len(uArr) > 0 {
		r.udmSubRepository.Delete(u.IMSI, neId)
		// 新增到拓展信息
		if u.Remark != "" {
			r.UDMExtendRepository.Delete(u.IMSI, "%")
			r.UDMExtendRepository.Inserts([]model.UDMExtend{{
				IMSI:   u.IMSI,
				MSISDN: u.MSISDN,
				NeId:   u.NeId,
				Remark: u.Remark,
			}})
		}
		return r.udmSubRepository.Inserts(uArr)
	}
	return 0
}

// InsertData 导入文件数据 dataType目前两种：txt/csv
func (r *UDMSubUser) InsertData(neId, dataType string, data any) int64 {
	// imsi截取前缀,重新获取部分数据
	prefixes := make(map[string]struct{})

	if dataType == "csv" {
		for _, v := range data.([]map[string]string) {
			imsi := v["imsi"]
			if len(imsi) < 6 {
				continue
			}
			prefix := imsi[:len(imsi)-4]
			prefixes[prefix] = struct{}{}
		}
	}
	if dataType == "txt" {
		for _, v := range data.([][]string) {
			imsi := v[0]
			if len(imsi) < 6 {
				continue
			}
			prefix := imsi[:len(imsi)-4]
			prefixes[prefix] = struct{}{}
		}
	}

	// 根据前缀重新加载插入
	var num int64 = 0
	for prefix := range prefixes {
		// keys udm-sd:4600001000004*
		arr := r.dataByRedis(prefix+"*", neId)
		if len(arr) > 0 {
			r.udmSubRepository.DeletePrefixByIMSI(prefix, neId)
			num += r.udmSubRepository.Inserts(arr)
		}
	}
	return num
}

// Delete 删除单个不重新加载
func (r *UDMSubUser) Delete(neId, imsi string) int64 {
	// 删除拓展信息
	r.UDMExtendRepository.Delete(imsi, neId)
	return r.udmSubRepository.Delete(imsi, neId)
}

// LoadData 重新加载从imsi开始num的数据
// remark不为空，则新增到拓展信息，删除标记为-(Deleted)-
func (r *UDMSubUser) LoadData(neId, imsi, num, remark string) {
	startIMSI, _ := strconv.ParseInt(imsi, 10, 64)
	subNum, _ := strconv.ParseInt(num, 10, 64)
	var i int64
	for i = 0; i < subNum; i++ {
		keyIMSI := fmt.Sprintf("%015d", startIMSI+i)
		// 删除原数据
		r.udmSubRepository.Delete(keyIMSI, neId)
		if remark == "-(Deleted)-" {
			r.UDMExtendRepository.Delete(keyIMSI, "%")
		}
		// 加载数据，删除标记为-(Deleted)-加载为空不插入
		arr := r.dataByRedis(keyIMSI, neId)
		if len(arr) < 1 {
			continue
		}
		r.udmSubRepository.Inserts(arr)
		// 拓展信息
		if remark != "" {
			uarr := make([]model.UDMExtend, 0, len(arr))
			for _, v := range arr {
				uarr = append(uarr, model.UDMExtend{
					IMSI:   v.IMSI,
					MSISDN: v.MSISDN,
					NeId:   v.NeId,
					Remark: remark,
				})
			}
			r.UDMExtendRepository.Delete(keyIMSI, neId)
			r.UDMExtendRepository.Inserts(uarr)
		}
	}
}

// ParseCommandParams 解析数据组成命令参数 msisdn=xx,xx=xx,...
func (r *UDMSubUser) ParseCommandParams(item model.UDMSubUser) string {
	var conditions []string
	if item.MSISDN != "" {
		conditions = append(conditions, fmt.Sprintf("msisdn=%s", item.MSISDN))
	}

	// AmData
	if item.UeAmbrTpl != "" {
		conditions = append(conditions, fmt.Sprintf("ambr=%s", item.UeAmbrTpl))
	}
	if item.NssaiTpl != "" {
		conditions = append(conditions, fmt.Sprintf("nssai=%s", item.NssaiTpl))
	}
	if item.AreaForbiddenTpl != "" {
		conditions = append(conditions, fmt.Sprintf("arfb=%s", item.AreaForbiddenTpl))
	}
	if item.ServiceAreaRestrictionTpl != "" {
		conditions = append(conditions, fmt.Sprintf("sar=%s", item.ServiceAreaRestrictionTpl))
	}
	if item.RatRestrictions != "" {
		conditions = append(conditions, fmt.Sprintf("rat=%s", item.RatRestrictions))
	}
	if item.CnTypeRestrictions != "" {
		conditions = append(conditions, fmt.Sprintf("cn=%s", item.CnTypeRestrictions))
	}
	if item.RfspIndex != "" {
		conditions = append(conditions, fmt.Sprintf("rfsp=%s", item.RfspIndex))
	}
	if item.UeUsageType != "" {
		conditions = append(conditions, fmt.Sprintf("usagetype=%s", item.UeUsageType))
	}
	if item.MicoAllowed != "" {
		conditions = append(conditions, fmt.Sprintf("mico=%s", item.MicoAllowed))
	}

	// EpsDat
	// if item.EpsDat != "" {
	// 	conditions = append(conditions, fmt.Sprintf("eps_dat=%s", item.EpsDat))
	// }
	if item.EpsFlag != "" {
		conditions = append(conditions, fmt.Sprintf("eps_flag=%s", item.EpsFlag))
	}
	if item.EpsOdb != "" {
		conditions = append(conditions, fmt.Sprintf("eps_odb=%s", item.EpsOdb))
	}
	if item.HplmnOdb != "" {
		conditions = append(conditions, fmt.Sprintf("hplmn_odb=%s", item.HplmnOdb))
	}
	if item.Epstpl != "" {
		conditions = append(conditions, fmt.Sprintf("epstpl=%s", item.Epstpl))
	}
	if item.Ard != "" {
		conditions = append(conditions, fmt.Sprintf("ard=%s", item.Ard))
	}
	if item.ContextId != "" {
		conditions = append(conditions, fmt.Sprintf("context_id=%s", item.ContextId))
	}
	if item.ApnContext != "" {
		conditions = append(conditions, fmt.Sprintf("apn_context=%s", item.ApnContext))
	}
	// static_ip指给4G UE分配的静态IP，没有可不带此字段名，批量添加IP会自动递增
	if item.StaticIp != "" {
		conditions = append(conditions, fmt.Sprintf("static_ip=%s", item.StaticIp))
	}

	// 其他
	if item.SmfSel != "" {
		conditions = append(conditions, fmt.Sprintf("smf_sel=%s", item.SmfSel))
	}
	if item.SmData != "" {
		conditions = append(conditions, fmt.Sprintf("sm_data=%s", item.SmData))
	}
	conditions = append(conditions, fmt.Sprintf("cag=%s", item.Cag))

	return strings.Join(conditions, ",")
}
