package controller

import (
	"fmt"
	"strings"
	"sync"

	"be.ems/src/framework/i18n"
	"be.ems/src/framework/utils/ctx"
	"be.ems/src/framework/utils/parse"
	"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"
)

// 实例化控制层 NeInfoController 结构体
var NewNeInfo = &NeInfoController{
	neInfoService: neService.NewNeInfoImpl,
}

// 网元信息请求
//
// PATH /
type NeInfoController struct {
	// 网元信息服务
	neInfoService neService.INeInfo
}

// neStateCacheMap 网元状态缓存最后一次成功的信息
var neStateCacheMap sync.Map
var mutex sync.Mutex

// 网元信息状态
//
// GET /state
func (s *NeInfoController) State(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var querys struct {
		NeType string `form:"neType" binding:"required"`
		NeID   string `form:"neId" binding:"required"`
	}
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
	if neInfo.NeId != querys.NeID || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}
	neKey := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)

	// 网元直连
	resData, err := neService.NeState(neInfo)
	if err != nil {
		mutex.Lock()
		// 异常取上次缓存
		resDataCache, ok := neStateCacheMap.Load(neKey)
		if ok && resDataCache != nil {
			resDataCache.(map[string]any)["online"] = false
		} else {
			resDataCache = map[string]any{
				"online": false,
				"neId":   neInfo.NeId,
				"neName": neInfo.NeName,
				"neType": neInfo.NeType,
				"neIP":   neInfo.IP,
			}
		}
		neStateCacheMap.Store(neKey, resDataCache)
		mutex.Unlock()
		c.JSON(200, result.OkData(resDataCache))
		return
	}

	// 存入缓存
	resData["online"] = true
	mutex.Lock()
	neStateCacheMap.Store(neKey, resData)
	mutex.Unlock()
	c.JSON(200, result.OkData(resData))
}

// 网元信息列表
//
// GET /list
func (s *NeInfoController) List(c *gin.Context) {
	querys := ctx.QueryMap(c)
	bandStatus := false
	if v, ok := querys["bandStatus"]; ok && v != nil {
		bandStatus = parse.Boolean(v)
	}
	data := s.neInfoService.SelectPage(querys, bandStatus)
	c.JSON(200, result.Ok(data))
}

// 网元信息列表全部无分页
//
// GET /listAll
func (s *NeInfoController) ListAll(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var querys struct {
		NeType     string `form:"neType"`
		NeId       string `form:"neId"`
		BandStatus string `form:"bandStatus"`
	}
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 查询实体参数
	ne := model.NeInfo{}
	if querys.NeType != "" {
		ne.NeType = querys.NeType
	}
	if querys.NeId != "" {
		ne.NeId = querys.NeId
	}
	bandStatus := parse.Boolean(querys.BandStatus)
	neList := s.neInfoService.SelectList(ne, bandStatus)
	if len(neList) == 0 {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}
	c.JSON(200, result.OkData(neList))
}

// 网元信息
//
// GET /:infoId
func (s *NeInfoController) Info(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	infoId := c.Param("infoId")
	if infoId == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neHost := s.neInfoService.SelectById(infoId, true)
	if neHost.ID != infoId {
		// 没有可访问网元信息数据！
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "neInfo.noData")))
		return
	}

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

// 网元neType和neID查询
//
// GET /
func (s *NeInfoController) NeTypeAndID(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var querys struct {
		NeType string `form:"neType" binding:"required"`
		NeID   string `form:"neId" binding:"required"`
	}
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
	if neInfo.NeId != querys.NeID || neInfo.IP == "" {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
		return
	}
	c.JSON(200, result.OkData(neInfo))
}

// 网元信息新增
//
// POST /
func (s *NeInfoController) Add(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body model.NeInfo
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.ID != "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 检查属性值唯一
	uniqueInfo := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, "")
	if !uniqueInfo {
		// 网元信息操作【%s】失败，同类型下标识已存在
		msg := i18n.TTemplate(language, "neInfo.errKeyExists", map[string]any{"key": body.NeId})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	// 获取网元状态是否正常
	_, err = neService.NeState(body)
	if err != nil {
		body.Status = "1"
	} else {
		// 下发网管配置信息给网元
		_, err = neService.NeConfigOMC(body)
		if err == nil {
			body.Status = "0"
		} else {
			body.Status = "3"
		}
	}

	insertId := s.neInfoService.Insert(body)
	if insertId != "" {
		c.JSON(200, result.Ok(nil))
		return
	}
	c.JSON(200, result.Err(nil))
}

// 网元信息修改
//
// PUT /
func (s *NeInfoController) Edit(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	var body model.NeInfo
	err := c.ShouldBindBodyWith(&body, binding.JSON)
	if err != nil || body.ID == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 检查属性值唯一
	uniqueHostCmd := s.neInfoService.CheckUniqueNeTypeAndNeId(body.NeType, body.NeId, body.ID)
	if !uniqueHostCmd {
		// 网元信息操作【%s】失败，同类型下标识已存在
		msg := i18n.TTemplate(language, "neInfo.errKeyExists", map[string]any{"key": body.NeId})
		c.JSON(200, result.ErrMsg(msg))
		return
	}

	// 检查是否存在
	neInfo := s.neInfoService.SelectById(body.ID, false)
	if neInfo.ID != body.ID {
		// 没有可访问网元信息数据！
		c.JSON(200, result.ErrMsg(i18n.TKey(language, "neInfo.noData")))
		return
	}

	// 获取网元状态是否正常
	_, err = neService.NeState(body)
	if err != nil {
		body.Status = "1"
	} else {
		// 下发网管配置信息给网元
		_, err = neService.NeConfigOMC(body)
		if err == nil {
			body.Status = "0"
		} else {
			body.Status = "3"
		}
	}

	rows := s.neInfoService.Update(body)
	if rows > 0 {
		c.JSON(200, result.Ok(nil))
		return
	}
	c.JSON(200, result.Err(nil))
}

// 网元信息删除
//
// DELETE /:infoIds
func (s *NeInfoController) Remove(c *gin.Context) {
	language := ctx.AcceptLanguage(c)
	infoIds := c.Param("infoIds")
	if infoIds == "" {
		c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	// 处理字符转id数组后去重
	ids := strings.Split(infoIds, ",")
	uniqueIDs := parse.RemoveDuplicates(ids)
	if len(uniqueIDs) <= 0 {
		c.JSON(200, result.Err(nil))
		return
	}
	rows, err := s.neInfoService.DeleteByIds(uniqueIDs)
	if err != nil {
		c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
		return
	}
	msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
	c.JSON(200, result.OkMsg(msg))
}
