package controller

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

	mmlclient "be.ems/lib/core/mml_client"
	"be.ems/src/framework/constants/uploadsubpath"
	"be.ems/src/framework/i18n"
	"be.ems/src/framework/utils/ctx"
	"be.ems/src/framework/utils/file"
	"be.ems/src/framework/utils/parse"
	"be.ems/src/framework/utils/ssh"
	"be.ems/src/framework/vo/result"
	"be.ems/src/modules/network_element/model"
	neService "be.ems/src/modules/network_element/service"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

// 实例化控制层 UDMSubController 结构体
var NewUDMSub = &UDMSubController{
	udmSubService: neService.NewUDMSubImpl,
	neInfoService: neService.NewNeInfoImpl,
}

// UDM签约用户请求
//
// PATH /udm/sub
type UDMSubController struct {
	// UDM鉴权信息服务
	udmSubService neService.IUDMSub
	// 网元信息服务
	neInfoService neService.INeInfo
}

// UDM签约用户-获取全部保存数据库
//
// POST /resetData/:neId
func (s *UDMSubController) ResetData(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	if neId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neId = ""
	data := s.udmSubService.Save(neId)
	c.JSON(200, result.OkData(data))
}

// UDM签约用户
//
// GET /list
func (s *UDMSubController) List(c *gin.Context) {
	querys := ctx.QueryMap(c)
	querys["neId"] = ""
	data := s.udmSubService.Page(querys)
	c.JSON(200, result.Ok(data))
}

// UDM签约用户-信息
//
// GET /:neId/:imsi
func (s *UDMSubController) Info(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	imsi := c.Param("imsi")
	if neId == "" || imsi == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}

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

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

	if len(data) == 0 {
		c.JSON(200, result.ErrMsg("No Subs Data"))
		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.UDMSub{
		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.udmSubService.List(model.UDMSub{NeID: neId, Imsi: imsi})
	if len(list) > 0 {
		listItme := list[0]
		userInfo.ID = listItme.ID
		s.udmSubService.Update(neId, userInfo)
	} else {
		s.udmSubService.Insert(neId, userInfo)
	}
	c.JSON(200, result.OkData(userInfo))
}

// UDM签约用户-增加
//
// POST /:neId
func (s *UDMSubController) Add(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	if neId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	var body model.UDMSub
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.Imsi == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		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 {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

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

// UDM签约用户-批量添加
//
// POST /:neId/:num
func (s *UDMSubController) Adds(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	num := c.Param("num")
	if neId == "" || num == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	var body model.UDMSub
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.Imsi == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}

	msg := fmt.Sprintf("baa 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 {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

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

// UDM签约用户-修改
//
// PUT /:neId
func (s *UDMSubController) Edit(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	if neId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	var body model.UDMSub
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.Imsi == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		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 {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

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

// UDM签约用户-删除
//
// DELETE /:neId/:imsi
func (s *UDMSubController) Remove(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	imsi := c.Param("imsi")
	if neId == "" || imsi == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 处理字符转id数组后去重
	imsiArr := strings.Split(imsi, ",")
	uniqueIDs := parse.RemoveDuplicates(imsiArr)
	if len(uniqueIDs) <= 0 {
		c.JSON(200, result.Err(nil))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}

	resultData := map[string]string{}
	for _, imsi := range uniqueIDs {
		msg := fmt.Sprintf("del udmuser:imsi=%s", imsi)

		// 发送MML
		data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
		if err != nil {
			resultData[imsi] = err.Error()
		}
		// 命令ok时
		if strings.Contains(data, "ok") {
			neId = ""
			s.udmSubService.Delete(neId, imsi)
			resultData[imsi] = data
		}
	}

	c.JSON(200, result.OkData(resultData))
}

// UDM签约用户-批量删除
//
// DELETE /:neId/:imsi/:num
func (s *UDMSubController) Removes(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.Param("neId")
	imsi := c.Param("imsi")
	num := c.Param("num")
	if neId == "" || imsi == "" || num == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		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 {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

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

// UDM签约用户-导出
//
// POST /export
func (s *UDMSubController) Export(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		NeId string `json:"neId" binding:"required"`
		Type string `json:"type" binding:"required"`
	}
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	if !(body.Type == "csv" || body.Type == "txt") {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
		return
	}

	neId := ""
	list := s.udmSubService.List(model.UDMSub{NeID: neId})
	// 文件名
	fileName := fmt.Sprintf("OMC_SUB_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
	filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), 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 {
			c.JSON(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 {
			c.JSON(200, result.ErrMsg(err.Error()))
			return
		}
	}

	c.FileAttachment(filePath, fileName)
}

// UDM签约用户-导入
//
// POST /import
func (s *UDMSubController) Import(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	neId := c.PostForm("neId")
	if neId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	formFile, err := c.FormFile("file")
	if err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	// 获取文件名
	if !(strings.HasSuffix(formFile.Filename, ".csv") || strings.HasSuffix(formFile.Filename, ".txt")) {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
		return
	}
	// 上传文件转存
	upFilePath, err := file.TransferUploadFile(formFile, uploadsubpath.IMPORT, nil)
	if err != nil {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
	if neInfo.NeId != neId || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}

	// 本地文件
	localPath := file.ParseUploadFilePath(upFilePath)
	nePath := "/tmp" //config.Get("mml.upload").(string)
	// 复制到远程
	err = ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
	if err != nil {
		c.JSON(200, result.ErrMsg(err.Error()))
		return
	}

	fileName := localPath[strings.LastIndex(localPath, "/")+1:]
	msg := fmt.Sprintf("import udmuser:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))

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

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