package udmuser

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"be.ems/features/udm_user/model"
	"be.ems/features/udm_user/service"
	"be.ems/lib/core/conf"
	mmlclient "be.ems/lib/core/mml_client"
	"be.ems/lib/core/utils/ctx"
	"be.ems/lib/core/vo/result"
	"be.ems/lib/dborm"
	"be.ems/lib/log"
	"be.ems/lib/midware"
	"be.ems/lib/services"
	"be.ems/restagent/config"
	"be.ems/src/framework/middleware/collectlogs"
	"be.ems/src/framework/utils/file"
	"be.ems/src/framework/utils/ssh"
)

// UDM 用户信息接口添加到路由
func Routers() []services.RouterItem {
	// 实例化控制层 SysDictTypeApi 结构体
	var apis = &UdmUserApi{
		authUser: *service.NewServiceUdmAuthUser,
		subUser:  *service.NewServiceUdmSubUser,
	}

	rs := [...]services.RouterItem{
		// UDM鉴权用户
		{
			Method:     "GET",
			Pattern:    "/auths",
			Handler:    apis.UdmAuthUserList,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "POST",
			Pattern:    "/authSave/{neId}",
			Handler:    apis.UdmAuthUserSave,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_INSERT)),
		},
		{
			Method:     "GET",
			Pattern:    "/auth/{neId}/{imsi}",
			Handler:    apis.UdmAuthUserInfo,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "POST",
			Pattern:    "/auth/{neId}",
			Handler:    apis.UdmAuthUserAdd,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_INSERT)),
		},
		{
			Method:     "POST",
			Pattern:    "/auth/{neId}/{num}",
			Handler:    apis.UdmAuthUserAdds,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_INSERT)),
		},
		{
			Method:     "PUT",
			Pattern:    "/auth/{neId}",
			Handler:    apis.UdmAuthUserEdit,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_UPDATE)),
		},
		{
			Method:     "DELETE",
			Pattern:    "/auth/{neId}/{imsi}",
			Handler:    apis.UdmAuthUserRemove,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_DELETE)),
		},
		{
			Method:     "DELETE",
			Pattern:    "/auth/{neId}/{imsi}/{num}",
			Handler:    apis.UdmAuthUserRemoves,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_DELETE)),
		},
		{
			Method:     "POST",
			Pattern:    "/authExport",
			Handler:    apis.UdmAuthUserExport,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_EXPORT)),
		},
		{
			Method:     "POST",
			Pattern:    "/authImport/{neId}",
			Handler:    apis.UdmAuthUserImport,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Authentication User", collectlogs.BUSINESS_TYPE_IMPORT)),
		},
		// UDM签约用户
		{
			Method:     "GET",
			Pattern:    "/subs",
			Handler:    apis.UdmSubUserList,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "POST",
			Pattern:    "/subSave/{neId}",
			Handler:    apis.UdmSubUserSave,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_INSERT)),
		},
		{
			Method:     "GET",
			Pattern:    "/subInfo/{neId}/{imsi}",
			Handler:    apis.UdmSubUserInfo,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "POST",
			Pattern:    "/sub/{neId}",
			Handler:    apis.UdmSubUserAdd,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_INSERT)),
		},
		{
			Method:     "POST",
			Pattern:    "/sub/{neId}/{num}",
			Handler:    apis.UdmSubUserAdds,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_INSERT)),
		},
		{
			Method:     "PUT",
			Pattern:    "/sub/{neId}",
			Handler:    apis.UdmSubUserEdit,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_UPDATE)),
		},
		{
			Method:     "PUT",
			Pattern:    "/sub4gIP/{neId}",
			Handler:    apis.UdmSubUser4GIP,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_UPDATE)),
		},
		{
			Method:     "PUT",
			Pattern:    "/subSmData/{neId}",
			Handler:    apis.UdmSubUserSmData,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_UPDATE)),
		},
		{
			Method:     "DELETE",
			Pattern:    "/sub/{neId}/{imsi}",
			Handler:    apis.UdmSubUserRemove,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_DELETE)),
		},
		{
			Method:     "DELETE",
			Pattern:    "/sub/{neId}/{imsi}/{num}",
			Handler:    apis.UdmSubUserRemoves,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_DELETE)),
		},
		{
			Method:     "POST",
			Pattern:    "/subExport",
			Handler:    apis.UdmSubUserExport,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_EXPORT)),
		},
		{
			Method:     "POST",
			Pattern:    "/subImport/{neId}",
			Handler:    apis.UdmSubUserImport,
			Middleware: midware.LogOperate(collectlogs.OptionNew("UDM Contracted User", collectlogs.BUSINESS_TYPE_IMPORT)),
		},
		// 添加更多的 Router 对象...
	}

	// 生成两组前缀路由
	rsPrefix := []services.RouterItem{}
	for _, v := range rs {
		path := "/udmUserManage/{apiVersion}" + v.Pattern
		// 固定前缀
		v.Pattern = config.DefaultUriPrefix + path
		rsPrefix = append(rsPrefix, v)
		// 可配置
		v.Pattern = config.UriPrefix + path
		rsPrefix = append(rsPrefix, v)
	}
	return rsPrefix
}

// NeInfoByUDM 网元信息
func NeInfoByUDM(neId string) (*dborm.NeInfo, error) {
	neInfo, err := dborm.XormGetNeInfo("UDM", neId)
	if err != nil {
		log.Error("dborm.XormGetNeInfo is failed:", err)
		return nil, err
	}
	if neInfo == nil || neInfo.Ip == "" {
		return nil, fmt.Errorf("not ne_info or not IP")
	}
	return neInfo, nil
}

// UDM 用户
//
// PATH /udmUserManage
type UdmUserApi struct {
	authUser service.ServiceUdmAuthUser
	subUser  service.ServiceUdmSubUser
}

// UDM鉴权用户
//
// GET /auths
func (s *UdmUserApi) UdmAuthUserList(w http.ResponseWriter, r *http.Request) {
	querys := ctx.QueryMap(r)
	querys["neId"] = ""
	data := s.authUser.Page(querys)
	ctx.JSON(w, 200, result.Ok(data))
}

// UDM鉴权用户-获取全部保存数据库
//
// POST /authSave/{neId}
func (s *UdmUserApi) UdmAuthUserSave(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neId = ""
	data := s.authUser.Save(neId)
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM鉴权用户-信息
//
// GET /authInfo/{neId}/{imsi}
func (s *UdmUserApi) UdmAuthUserInfo(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	imsi := ctx.Param(r, "imsi")
	if neId == "" || imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("dsp authdat:imsi=%s", imsi)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToMap(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 查询数据库是否存在并存入
	neId = ""
	var userInfo model.UdmAuthUser
	list := s.authUser.List(model.UdmAuthUser{NeID: neId, Imsi: imsi})
	if len(list) > 0 {
		userInfo = list[0]
		// 返回查询的用户信息
		userInfo.Amf = data["amf"]
		userInfo.AlgoIndex = data["algo"]
		userInfo.Opc = data["opc"]
		userInfo.Ki = data["ki"]
	} else {
		userInfo := model.UdmAuthUser{
			Imsi:      imsi,
			Amf:       data["amf"],
			AlgoIndex: data["algo"],
			Opc:       data["opc"],
			Ki:        data["ki"],
		}
		s.authUser.Insert(neId, userInfo)
	}
	ctx.JSON(w, 200, result.OkData(userInfo))

}

// UDM鉴权用户-增加
//
// POST /{neId}
func (s *UdmUserApi) UdmAuthUserAdd(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmAuthUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("add authdat:imsi=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.Imsi, body.Ki, body.Amf, body.AlgoIndex, body.Opc)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.authUser.Insert(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM鉴权用户-批量添加
//
// POST /{neId}/{num}
func (s *UdmUserApi) UdmAuthUserAdds(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	num := ctx.Param(r, "num")
	if neId == "" || num == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmAuthUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("bad authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.Imsi, num, body.Ki, body.Amf, body.AlgoIndex, body.Opc)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.authUser.Inserts(neId, body, num)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM鉴权用户-修改
//
// PUT /{neId}
func (s *UdmUserApi) UdmAuthUserEdit(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmAuthUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("mod authdata:imsi=%s", body.Imsi)
	// 修改的参数名称
	if body.Ki != "" {
		msg += fmt.Sprintf(",ki=%s", body.Ki)
	}
	if body.Amf != "" {
		msg += fmt.Sprintf(",amf=%s", body.Amf)
	}
	if body.AlgoIndex != "" {
		msg += fmt.Sprintf(",algo=%s", body.AlgoIndex)
	}
	if body.Opc != "" {
		msg += fmt.Sprintf(",opc=%s", body.Opc)
	}

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.authUser.Update(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM鉴权用户-删除
//
// DELETE /{neId}/{imsi}
func (s *UdmUserApi) UdmAuthUserRemove(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	imsi := ctx.Param(r, "imsi")
	if neId == "" || imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("del authdat:imsi=%s", imsi)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.authUser.Delete(neId, imsi)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM鉴权用户-批量删除
//
// DELETE /{neId}/{imsi}/{num}
func (s *UdmUserApi) UdmAuthUserRemoves(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	imsi := ctx.Param(r, "imsi")
	num := ctx.Param(r, "num")
	if neId == "" || imsi == "" || num == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("bde authdat:start_imsi=%s,sub_num=%s", imsi, num)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.authUser.Deletes(neId, imsi, num)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM鉴权用户-导出
//
// POST /authExport
func (s *UdmUserApi) UdmAuthUserExport(w http.ResponseWriter, r *http.Request) {
	var body struct {
		NeId string `json:"neId"`
		Type string `json:"type"`
	}
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.NeId == "" || body.Type == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	if !(body.Type == "csv" || body.Type == "txt") {
		ctx.JSON(w, 200, result.ErrMsg("Export file types support CSV and txt"))
		return
	}

	neId := ""
	list := s.authUser.List(model.UdmAuthUser{NeID: neId})
	// 文件名
	fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
	filePath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName)

	if body.Type == "csv" {
		// 转换数据
		data := [][]string{}
		data = append(data, []string{"imsi", "ki", "algo", "amf", "opc"})
		for _, v := range list {
			data = append(data, []string{v.Imsi, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
		}
		// 输出到文件
		err := file.WriterFileCSV(data, filePath)
		if err != nil {
			ctx.JSON(w, 200, result.ErrMsg(err.Error()))
			return
		}
	}

	if body.Type == "txt" {
		// 转换数据
		data := [][]string{}
		for _, v := range list {
			data = append(data, []string{v.Imsi, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
		}
		// 输出到文件
		err = file.WriterFileTXT(data, ",", filePath)
		if err != nil {
			ctx.JSON(w, 200, result.ErrMsg(err.Error()))
			return
		}
	}

	ctx.FileAttachment(w, r, filePath, fileName)
}

// UDM鉴权用户-导入
//
// POST /authImport/{neId}
func (s *UdmUserApi) UdmAuthUserImport(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	// 获取文件名
	_, fileHeader, err := r.FormFile("file")
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}
	if !(strings.HasSuffix(fileHeader.Filename, ".csv") || strings.HasSuffix(fileHeader.Filename, ".txt")) {
		ctx.JSON(w, 200, result.ErrMsg("Please upload files in. csv and. txt formats with content fields: imsi,ki,algo,amf,opc"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 文件名
	fileName := fmt.Sprintf("OMC_AUTH_USER_IMPORT_%s_%d_%s", neId, time.Now().UnixMilli(), fileHeader.Filename)
	localPath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName)
	nePath := conf.Get("mml.upload").(string)
	// 输出保存文件
	err = ctx.SaveUploadedFile(r, localPath)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 复制到远程
	err = ssh.FileSCPLocalToNe(neInfo.Ip, localPath, nePath)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("import authdat:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		if strings.HasSuffix(fileHeader.Filename, ".csv") {
			data := file.ReadFileCSV(localPath)
			neId = ""
			go s.authUser.InsertCSV(neId, data)
		}
		if strings.HasSuffix(fileHeader.Filename, ".txt") {
			data := file.ReadFileTXT(",", localPath)
			neId = ""
			go s.authUser.InsertTxt(neId, data)
		}
	}
	ctx.JSON(w, 200, result.OkMsg(data))
}

// UDM签约用户
//
// GET /subs
func (s *UdmUserApi) UdmSubUserList(w http.ResponseWriter, r *http.Request) {
	querys := ctx.QueryMap(r)
	querys["neId"] = ""
	data := s.subUser.Page(querys)
	ctx.JSON(w, 200, result.Ok(data))
}

// UDM签约用户-获取全部保存数据库
//
// POST /subSave/{neId}
func (s *UdmUserApi) UdmSubUserSave(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neId = ""
	data := s.subUser.Save(neId)
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-信息
//
// GET /subInfo/{neId}/{imsi}
func (s *UdmUserApi) UdmSubUserInfo(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	imsi := ctx.Param(r, "imsi")
	if neId == "" || imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("dsp udmuser:imsi=%s", imsi)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToMap(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 解析返回的数据
	cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64)
	rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64)
	msisdn := data["MSISDN"]
	imsMsisdnLen := strings.Index(msisdn, ",")
	if imsMsisdnLen != -1 {
		msisdn = msisdn[:imsMsisdnLen]
	}
	userInfo := model.UdmSubUser{
		Imsi:   imsi,
		Msisdn: msisdn,
		Ambr:   data["AMBR"],
		Arfb:   data["AreaForbidden"],
		Cn:     fmt.Sprint(cnType),
		SmData: data["SM-Data(snssai+dnn[1..n])"],
		Sar:    data["ServiceAreaRestriction"],
		Nssai:  data["NSSAI"],
		SmfSel: data["Smf-Selection"],
		Rat:    fmt.Sprint(rat),
	}
	// 1,64,24,65,def_eps,1,2,010200000000,-
	if v, ok := data["EPS-Data"]; ok {
		userInfo.EpsDat = v
		arr := strings.Split(v, ",")
		userInfo.EpsFlag = arr[0]
		userInfo.EpsOdb = arr[1]
		userInfo.HplmnOdb = arr[2]
		userInfo.Ard = arr[3]
		userInfo.Epstpl = arr[4]
		userInfo.ContextId = arr[5]
		userInfo.ApnContext = arr[7]
		userInfo.StaticIp = arr[8]
	}

	// 查询数据库是否存在并存入更新
	neId = ""
	list := s.subUser.List(model.UdmSubUser{NeID: neId, Imsi: imsi})
	if len(list) > 0 {
		listItme := list[0]
		userInfo.ID = listItme.ID
		s.subUser.Update(neId, userInfo)
	} else {
		s.subUser.Insert(neId, userInfo)
	}
	ctx.JSON(w, 200, result.OkData(userInfo))
}

// UDM签约用户-增加
//
// POST /{neId}
func (s *UdmUserApi) UdmSubUserAdd(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmSubUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("add udmuser:imsi=%s,msisdn=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
		body.Imsi, body.Msisdn, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
	//  static_ip指给4G UE分配的静态IP，没有可不带此字段名，批量添加IP会自动递增
	if body.StaticIp != "" {
		msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
	}

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Insert(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-批量添加
//
// POST /{neId}/{num}
func (s *UdmUserApi) UdmSubUserAdds(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	num := ctx.Param(r, "num")
	if neId == "" || num == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmSubUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("bad udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
		body.Imsi, body.Msisdn, num, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
	//  static_ip指给4G UE分配的静态IP，没有可不带此字段名，批量添加IP会自动递增
	if body.StaticIp != "" {
		msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
	}

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Inserts(neId, body, num)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-批量添加4G用户
//
// POST  /sub4G/{neId}
func (s *UdmUserApi) UdmSubUserAdd4G(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmSubUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" || body.SubNum == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("bmd udmuser:start_imsi=%s,sub_num=%s,eps_flag=%s", body.Imsi, body.SubNum, body.EpsFlag)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Insert4G(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-修改
//
// PUT /{neId}
func (s *UdmUserApi) UdmSubUserEdit(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmSubUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("mod udmuser:imsi=%s", body.Imsi)
	// 修改的参数名称
	if body.Msisdn != "" {
		msg += fmt.Sprintf(",msisdn=%s", body.Msisdn)
	}
	if body.Ambr != "" {
		msg += fmt.Sprintf(",ambr=%s", body.Ambr)
	}
	if body.Nssai != "" {
		msg += fmt.Sprintf(",nssai=%s", body.Nssai)
	}
	if body.Arfb != "" {
		msg += fmt.Sprintf(",arfb=%s", body.Arfb)
	}
	if body.Sar != "" {
		msg += fmt.Sprintf(",sar=%s", body.Sar)
	}
	if body.Rat != "" {
		msg += fmt.Sprintf(",rat=%s", body.Rat)
	}
	if body.Cn != "" {
		msg += fmt.Sprintf(",cn=%s", body.Cn)
	}
	if body.SmfSel != "" {
		msg += fmt.Sprintf(",smf_sel=%s", body.SmfSel)
	}
	if body.SmData != "" {
		msg += fmt.Sprintf(",sm_data=%s", body.SmData)
	}
	if body.EpsDat != "" {
		msg += fmt.Sprintf(",eps_dat=%s", body.EpsDat)
	}
	if body.EpsFlag != "" {
		msg += fmt.Sprintf(",eps_flag=%s", body.EpsFlag)
	}
	if body.EpsOdb != "" {
		msg += fmt.Sprintf(",eps_odb=%s", body.EpsOdb)
	}
	if body.HplmnOdb != "" {
		msg += fmt.Sprintf(",hplmn_odb=%s", body.HplmnOdb)
	}
	if body.Epstpl != "" {
		msg += fmt.Sprintf(",epstpl=%s", body.Epstpl)
	}
	if body.Ard != "" {
		msg += fmt.Sprintf(",ard=%s", body.Ard)
	}
	if body.ContextId != "" {
		msg += fmt.Sprintf(",context_id=%s", body.ContextId)
	}
	if body.ApnContext != "" {
		msg += fmt.Sprintf(",apn_context=%s", body.ApnContext)
	}
	if body.StaticIp != "" {
		msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
	}

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Update(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-批量修改4G IP
//
// PUT /sub4gIP/{neId}
func (s *UdmUserApi) UdmSubUser4GIP(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmSubUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" || body.SubNum == "" || body.StaticIp == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("bmd udmuser:start_imsi=%s,sub_num=%s,static_ip=%s", body.Imsi, body.SubNum, body.StaticIp)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}
	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Update4GIP(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-批量修改sm-data
//
// PUT /subSmData/{neId}
func (s *UdmUserApi) UdmSubUserSmData(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	var body model.UdmSubUser
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.Imsi == "" || body.SubNum == "" || body.SmData == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 3-000003&internet-10.10.1.1&ims-10.11.1.1
	msg := fmt.Sprintf("bmd udmuser:start_imsi=%s,sub_num=%s,sm_data=%s", body.Imsi, body.SubNum, body.SmData)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}
	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.UpdateSmData(neId, body)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-删除
//
// DELETE /{neId}/{imsi}
func (s *UdmUserApi) UdmSubUserRemove(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	imsi := ctx.Param(r, "imsi")
	if neId == "" || imsi == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("del udmuser:imsi=%s", imsi)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Delete(neId, imsi)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-批量删除
//
// DELETE /{neId}/{imsi}/{num}
func (s *UdmUserApi) UdmSubUserRemoves(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	imsi := ctx.Param(r, "imsi")
	num := ctx.Param(r, "num")
	if neId == "" || imsi == "" || num == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("bde udmuser:start_imsi=%s,sub_num=%s", imsi, num)

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 命令ok时
	if strings.Contains(data, "ok") {
		neId = ""
		s.subUser.Deletes(neId, imsi, num)
	}
	ctx.JSON(w, 200, result.OkData(data))
}

// UDM签约用户-导出
//
// POST /subExport
func (s *UdmUserApi) UdmSubUserExport(w http.ResponseWriter, r *http.Request) {
	var body struct {
		NeId string `json:"neId"`
		Type string `json:"type"`
	}
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.NeId == "" || body.Type == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	if !(body.Type == "csv" || body.Type == "txt") {
		ctx.JSON(w, 200, result.ErrMsg("Export file type support csv、txt"))
		return
	}

	neId := ""
	list := s.subUser.List(model.UdmSubUser{NeID: neId})
	// 文件名
	fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
	filePath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName)

	if body.Type == "csv" {
		// 转换数据
		data := [][]string{}
		data = append(data, []string{"imsi", "msisdn", "ambr", "nssai", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"})
		for _, v := range list {
			epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
			data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
		}
		// 输出到文件
		err = file.WriterFileCSV(data, filePath)
		if err != nil {
			ctx.JSON(w, 200, result.ErrMsg(err.Error()))
			return
		}
	}

	if body.Type == "txt" {
		// 转换数据
		data := [][]string{}
		for _, v := range list {
			epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
			data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
		}
		// 输出到文件
		err = file.WriterFileTXT(data, ",", filePath)
		if err != nil {
			ctx.JSON(w, 200, result.ErrMsg(err.Error()))
			return
		}
	}

	ctx.FileAttachment(w, r, filePath, fileName)
}

// UDM签约用户-导入
//
// POST /subImport/{neId}
func (s *UdmUserApi) UdmSubUserImport(w http.ResponseWriter, r *http.Request) {
	neId := ctx.Param(r, "neId")
	if neId == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	// 获取文件名
	_, fileHeader, err := r.FormFile("file")
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}
	if !(strings.HasSuffix(fileHeader.Filename, ".csv") || strings.HasSuffix(fileHeader.Filename, ".txt")) {
		ctx.JSON(w, 200, result.ErrMsg("Please upload files in. csv and. txt formats with content fields: imsi,msisdn,ambr,nssai,arfb,sar,rat,cn,smf_sel,sm_dat,eps_dat"))
		return
	}

	neInfo, err := NeInfoByUDM(neId)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 文件名
	fileName := fmt.Sprintf("OMC_SUB_USER_IMPORT_%s_%d_%s", neId, time.Now().UnixMilli(), fileHeader.Filename)
	localPath := fmt.Sprintf("%s/upload/mml/%s", conf.Get("ne.omcdir"), fileName)
	nePath := conf.Get("mml.upload").(string)
	// 输出保存文件
	err = ctx.SaveUploadedFile(r, localPath)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	// 复制到远程
	err = ssh.FileSCPLocalToNe(neInfo.Ip, localPath, nePath)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}

	msg := fmt.Sprintf("import udmuser:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))

	// 发送MML
	data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}
	// 命令ok时
	if strings.Contains(data, "ok") {
		if strings.HasSuffix(fileHeader.Filename, ".csv") {
			data := file.ReadFileCSV(localPath)
			neId = ""
			go s.subUser.InsertCSV(neId, data)
		}
		if strings.HasSuffix(fileHeader.Filename, ".txt") {
			data := file.ReadFileTXT(",", localPath)
			neId = ""
			go s.subUser.InsertTxt(neId, data)
		}
	}
	ctx.JSON(w, 200, result.OkMsg(data))
}
