package controller

import (
	"fmt"
	"nms_nbi/src/framework/config"
	"nms_nbi/src/framework/i18n"
	"nms_nbi/src/framework/utils/cmd"
	"nms_nbi/src/framework/utils/ctx"
	"nms_nbi/src/framework/utils/date"
	"nms_nbi/src/framework/utils/ping"
	"nms_nbi/src/framework/vo/result"
	"nms_nbi/src/modules/api_rest_cxy/service"
	"nms_nbi/src/modules/api_rest_cxy/utils/common"
	neService "nms_nbi/src/modules/network_element/service"

	"time"

	"github.com/gin-gonic/gin"
)

// 实例化控制层 SystemController 结构体
var NewSystem = &SystemController{
	neInfoService:     neService.NewNeInfoImpl,
	neVersionService:  neService.NewNeVersionImpl,
	neSoftwareService: neService.NewNeSoftwareImpl,
	alarmService:      service.NewAlarmImpl,
	logService:        service.NewLogImpl,
}

// 系统管理接口
//
// PATH /systemManagement
type SystemController struct {
	// 网元信息服务
	neInfoService neService.INeInfo
	// 网元版本信息服务
	neVersionService neService.INeVersion
	// 网元软件包信息服务
	neSoftwareService neService.INeSoftware
	// 告警数据服务
	alarmService service.IAlarm
	// 日志数据服务
	logService service.ILog
}

// 软件版本查询接口
//
// GET /:apiVersion/softwareVersion
func (s *SystemController) SoftwareVersionInfo(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	neVersion := s.neVersionService.SelectByTypeAndID(neInfo.NeType, neInfo.NeId)
	if neVersion.ID == "" {
		c.JSON(200, map[string]any{
			"requestId":         body.RequestId,
			"currentVersion":    "-",
			"backupVersionList": []string{"-"},
		})
		return
	}
	c.JSON(200, map[string]any{
		"requestId":         body.RequestId,
		"currentVersion":    neVersion.Version,
		"backupVersionList": []string{neVersion.PreVersion},
	})
}

// 软件下载请求接口
//
// POST /:apiVersion/softwareDownload
func (s *SystemController) SoftwareDownloadCheck(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId       string `json:"requestId" binding:"required"`
		SoftwareVersion string `json:"softwareVersion" binding:"required"`
		DownloadPath    string `json:"downloadPath" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neSoftware := s.neSoftwareService.SelectByVersionAndPath(body.SoftwareVersion, body.DownloadPath)
	if neSoftware.Version != body.SoftwareVersion {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
	})
}

// 软件下载状态查询接口
//
// GET /:apiVersion/softwareDownload
func (s *SystemController) SoftwareDownloadState(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	if len(body.RequestId) < 5 {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId":      body.RequestId,
		"status":         "fail",
		"additionalInfo": "Download path not exist",
	})
}

// 软件更新请求接口
//
// POST /:apiVersion/softwareUpdate
func (s *SystemController) SoftwareUpdateVersion(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId     string `json:"requestId" binding:"required"`
		Ruid          string `json:"ruid" binding:"required"`
		UpdateVersion string `json:"updateVersion" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	neVersion := s.neVersionService.SelectByTypeAndID(neInfo.NeType, neInfo.NeId)
	if neVersion.ID == "" {
		c.JSON(200, map[string]any{
			"requestId":         body.RequestId,
			"currentVersion":    "-",
			"backupVersionList": []string{"-"},
		})
		return
	}

	// 更新版本号
	neVersion.Version = body.UpdateVersion
	rows := s.neVersionService.Update(neVersion)
	if rows > 0 {
		c.JSON(200, map[string]any{
			"requestId": body.RequestId,
		})
		return
	}
	c.JSON(500, map[string]any{
		"requestId": body.RequestId,
		"errorInfo": "Update Version Fail",
	})
}

// 软件更新状态查询接口
//
// GET /:apiVersion/softwareUpdate
func (s *SystemController) SoftwareUpdateState(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId":      body.RequestId,
		"status":         "fail",
		"additionalInfo": "software not compatible",
	})
}

// 网元重启请求接口
//
// POST /:apiVersion/reboot
func (s *SystemController) RebootApp(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	_, err := cmd.ExecWithCheck("nohup", "sh", "-c", "sleep 2s && service restagent restart", "&")
	if err != nil {
		c.JSON(200, map[string]any{
			"requestId":      body.RequestId,
			"status":         "fail",
			"additionalInfo": fmt.Sprintf("NE service reboot error %s", err.Error()),
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
	})
}

// 网元重启状态查询接口
//
// GET /:apiVersion/reboot
func (s *SystemController) RebootState(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	// 获取程序运行时间
	runTime := time.Since(config.RunTime()).Abs().Seconds()
	if runTime > 120 {
		c.JSON(200, map[string]any{
			"requestId":      body.RequestId,
			"status":         "fail",
			"additionalInfo": "NE not implement",
		})
		return
	}
	c.JSON(200, map[string]any{
		"requestId":      body.RequestId,
		"status":         "success",
		"additionalInfo": "NE successfully restarted",
	})
}

// 恢复出厂配置请求接口
//
// POST /:apiVersion/reinitiate
func (s *SystemController) ReinitiateApp(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
	})
}

// 恢复出厂配置状态查询接口
//
// GET /:apiVersion/reinitiate
func (s *SystemController) ReinitiateState(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId":      body.RequestId,
		"status":         "fail",
		"additionalInfo": "NE not implement",
	})
}

// 配置修改接口
//
// POST /:apiVersion/config
func (s *SystemController) ConfigApp(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
		OperType  string `json:"operType" binding:"required"`
		OperPara  any    `json:"operPara" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
		"status":    "partialsuccess",
		"failPara":  []string{"PhyCellID", "TAC"},
	})
}

// 配置查询接口
//
// GET /:apiVersion/config
func (s *SystemController) ConfigInfo(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string   `json:"requestId" binding:"required"`
		Ruid      string   `json:"ruid" binding:"required"`
		QueryPara []string `json:"queryPara" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
		"status":    "partialsuccess",
		"successPara": map[string]any{
			"cellIdentity": "1234567890",
			"PhyCellID":    "12345",
			"TAC":          "12345",
		},
	})
}

// 告警文件同步请求接口
//
// 告警实时上报通过kafka推送到topic
//
// POST /:apiVersion/alarm
func (s *SystemController) AlarmSysnc(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
		StartTime string `json:"startTime" binding:"required"`
		EndTime   string `json:"endTime" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 时间格式校验
	startTime := date.ParseStrToDate(body.StartTime, date.YYYY_MM_DD_HH_MM_SS)
	if startTime.IsZero() {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	endTime := date.ParseStrToDate(body.EndTime, date.YYYY_MM_DD_HH_MM_SS)
	if endTime.IsZero() {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询网元是否存在
	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	sysncNum, filePath := s.alarmService.AlarmDataToFile(body.RequestId, neInfo.NeType, neInfo.RmUID, body.StartTime, body.EndTime)
	if sysncNum > 0 {
		common.UploadOSSByJSONToZip(filePath, neInfo.NeType, "FM")
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
		"sysncNum":  sysncNum,
	})
}

// 日志数据同步请求接口
//
// POST /:apiVersion/log
func (s *SystemController) LogSysnc(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		Ruid      string `json:"ruid" binding:"required"`
		LogType   string `json:"logType"`                      // operate、security、other
		StartTime string `json:"startTime" binding:"required"` // 2022-12-15 08:34:24
		EndTime   string `json:"endTime" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 时间格式校验
	startTime := date.ParseStrToDate(body.StartTime, date.YYYY_MM_DD_HH_MM_SS)
	if startTime.IsZero() {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	endTime := date.ParseStrToDate(body.EndTime, date.YYYY_MM_DD_HH_MM_SS)
	if endTime.IsZero() {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByRmuid(body.Ruid)
	if neInfo.RmUID != body.Ruid {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "NE not exist",
		})
		return
	}

	if body.LogType == "operate" {
		sysncNum, filePath := s.logService.OperateLogToFile(language, body.StartTime, body.EndTime)
		if sysncNum > 0 {
			common.UploadOSSByJSONToZip(filePath, neInfo.NeType, "LOG")
		}
		c.JSON(200, map[string]any{
			"requestId": body.RequestId,
			"sysncNum":  sysncNum,
		})
		return
	}

	if body.LogType == "security" {
		sysncNum, filePath := s.logService.SecurityLogToFile(language, body.StartTime, body.EndTime)
		if sysncNum > 0 {
			common.UploadOSSByJSONToZip(filePath, neInfo.NeType, "LOG")
		}
		c.JSON(200, map[string]any{
			"requestId": body.RequestId,
			"sysncNum":  sysncNum,
		})
		return
	}

	c.JSON(500, map[string]any{
		"requestId": body.RequestId,
		"errorInfo": "logType not found",
	})
}

// 业务诊断请求接口
//
// POST /:apiVersion/diagnose
func (s *SystemController) Diagnose(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string         `json:"requestId" binding:"required"`
		Ruid      string         `json:"ruid" binding:"required"`
		OperType  string         `json:"operType" binding:"required,oneof=ping trace"`
		OperPara  map[string]any `json:"operPara" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	operPara := body.OperPara
	// 必填目的 IP 地址（字符串类型，必填）
	desAddr, desAddrOk := operPara["desAddr"]
	if !desAddrOk || desAddr == nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 端到端ping检测
	if body.OperType == "ping" {
		p := ping.Ping{}
		p.CopyFrom(operPara)
		info, err := p.StatsInfo()
		if err != nil {
			c.JSON(500, map[string]any{
				"requestId": body.RequestId,
				"errorInfo": fmt.Sprintf("ping fail %s", err.Error()),
			})
			return
		}
		c.JSON(200, map[string]any{
			"requestId":  body.RequestId,
			"operResult": info,
		})
		return
	}

	// 端到端Trace检测
	if body.OperType == "trace" {
		p := ping.Ping{}
		p.CopyFrom(operPara)
		info, err := p.StatsRtt()
		if err != nil {
			c.JSON(500, map[string]any{
				"requestId": body.RequestId,
				"errorInfo": fmt.Sprintf("ping fail %s", err.Error()),
			})
			return
		}
		c.JSON(200, map[string]any{
			"requestId":  body.RequestId,
			"operResult": info,
		})
		return
	}

	c.JSON(500, map[string]any{
		"requestId": body.RequestId,
		"errorInfo": "operType not found",
	})
}

// 业务连续性功能控制接口
//
// POST /:apiVersion/servicecontinuity
func (s *SystemController) ServiceContinuity(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body struct {
		RequestId string `json:"requestId" binding:"required"`
		OperType  int    `json:"operType" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	if body.OperType > 1 {
		c.JSON(500, map[string]any{
			"requestId": body.RequestId,
			"errorInfo": "operType not support",
		})
		return
	}

	c.JSON(200, map[string]any{
		"requestId": body.RequestId,
	})
}
