package controller

import (
	"fmt"
	"strings"

	"github.com/gin-gonic/gin"

	"be.ems/src/framework/i18n"
	"be.ems/src/framework/reqctx"
	"be.ems/src/framework/resp"
	neService "be.ems/src/modules/ne/service"
	"be.ems/src/modules/tool/model"
	"be.ems/src/modules/tool/service"
)

// 实例化控制层 MMLController 结构体
var NewMML = &MMLController{
	neInfoService:        neService.NewNeInfo,
	mmlSystemService:     service.NewMMLSystem,
	mmlSubscriberService: service.NewMMLSubscriber,
	mmlLogService:        service.NewMMLLog,
}

// MML 网元MML
//
// PATH /tool/mml
type MMLController struct {
	neInfoService        *neService.NeInfo // 网元信息服务
	mmlSystemService     *service.MMLSystem
	mmlSubscriberService *service.MMLSubscriber
	mmlLogService        *service.MMLLog
}

// SystemList MML网元列表
//
// GET /system/list
func (s MMLController) SystemList(c *gin.Context) {
	query := reqctx.QueryMap(c)
	rows, total := s.mmlSystemService.FindByPage(query)
	c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}

// SubscriberList MML网元UDM列表
//
// GET /subscriber/list
func (s MMLController) SubscriberList(c *gin.Context) {
	query := reqctx.QueryMap(c)
	rows, total := s.mmlSubscriberService.FindByPage(query)
	c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}

// LogList MML日志列表
//
// GET /log/list
func (s MMLController) LogList(c *gin.Context) {
	query := reqctx.QueryMap(c)
	rows, total := s.mmlLogService.FindByPage(query)
	c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}

// Command MML命令执行
//
// POST /command
func (s MMLController) Command(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	var body struct {
		NeType  string   `json:"neType" binding:"required"`                      // 网元类型
		NeId    string   `json:"neId" binding:"required"`                        // 网元ID
		Command []string `json:"command" binding:"required"`                     // 命令
		Type    string   `json:"type" binding:"required,oneof=General Standard"` // 类型UPF标准版 General Standard
	}
	if err := c.ShouldBindBodyWithJSON(&body); err != nil {
		errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
		c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
		return
	}

	// 查询网元获取IP
	neInfo := s.neInfoService.FindByNeTypeAndNeID(body.NeType, body.NeId)
	if neInfo.NeId != body.NeId || neInfo.IP == "" {
		c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}
	// 网元主机的Telnet客户端
	num := 1
	if body.NeType == "UPF" && body.Type == "Standard" {
		num = 2
	}
	telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, num)
	if err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}
	defer telnetClient.Close()
	if body.NeType != "IMS" {
		telnetClient.RunCMD("\r\n")
	}
	if body.NeType == "UPF" && body.Type == "Standard" {
		telnetClient.WindowChange(1024, 1024)
	}
	// 发送MML
	result := []string{}
	resultStr := "Success"
	hasCommand := false
	for _, v := range body.Command {
		if v == "" {
			continue
		}
		if strings.Contains(v, "dec key") {
			hasCommand = true
		}
		output, err := telnetClient.RunCMD(v + "\r\n")
		if err != nil {
			result = append(result, err.Error())
			resultStr = "there is an error"
			continue
		}
		result = append(result, strings.TrimSpace(output))
	}

	// UDM 特殊命令处理
	if body.NeType == "UDM" && hasCommand {
		output, err := s.neInfoService.NeRunSSHCmd(neInfo.NeType, neInfo.NeId, "cat /usr/local/etc/udm/ueKeyProfile.tmp")
		if err != nil {
			result = append(result, err.Error())
		} else {
			result = append(result, output)
		}
	}

	// 记录日志
	mmlLog := model.MMLLog{
		NeType:  body.NeType,
		NeId:    body.NeId,
		User:    reqctx.LoginUserToUserName(c),
		Ip:      c.ClientIP(),
		Command: strings.Join(body.Command, ";"),
		Result:  resultStr,
	}
	s.mmlLogService.Insert(mmlLog)
	c.JSON(200, resp.OkData(result))
}
