package controller

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"be.ems/src/framework/i18n"
	"be.ems/src/framework/reqctx"
	"be.ems/src/framework/resp"
	"be.ems/src/framework/utils/file"
	"be.ems/src/framework/utils/parse"
	"be.ems/src/modules/ne/model"
	neService "be.ems/src/modules/ne/service"
	systemService "be.ems/src/modules/system/service"

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

// NewNeConfigBackup 实例化控制层 NeConfigBackupController 结构体
var NewNeConfigBackup = &NeConfigBackupController{
	neConfigBackupService: neService.NewNeConfigBackup,
	neInfoService:         neService.NewNeInfo,
	sysConfigService:      systemService.NewSysConfig,
}

// 网元配置文件备份记录
//
// PATH /config/backup
type NeConfigBackupController struct {
	neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
	neInfoService         *neService.NeInfo         // 网元信息服务
	sysConfigService      *systemService.SysConfig  // 参数配置服务
}

// 网元配置文件备份记录列表
//
// GET /list
func (s NeConfigBackupController) List(c *gin.Context) {
	query := reqctx.QueryMap(c)
	rows, total := s.neConfigBackupService.FindByPage(query)
	c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total}))
}

// 网元配置文件备份记录信息
//
// GET /download?id=xx
func (s NeConfigBackupController) Download(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	id := parse.Number(c.Query("id"))
	if id <= 0 {
		c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
		return
	}

	item := s.neConfigBackupService.FindById(id)
	if item.ID != id {
		// 没有可访问主机命令数据！
		c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfigBackup.noData")))
		return
	}

	if _, err := os.Stat(item.Path); err != nil {
		c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfigBackup.notFoundFile")))
		return
	}
	c.FileAttachment(item.Path, item.Name)
}

// 网元配置文件备份记录修改
//
// PUT /
func (s NeConfigBackupController) Edit(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	var body struct {
		ID     int64  `json:"id" binding:"required"`     // 记录ID
		Name   string `json:"name" binding:"required"`   // 名称
		Remark string `json:"remark" binding:"required"` // 备注
	}
	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
	}

	// 检查是否存在
	data := s.neConfigBackupService.FindById(body.ID)
	if data.ID != body.ID {
		// 没有可访问主机命令数据！
		c.JSON(200, resp.ErrMsg(i18n.TKey(language, "neConfig.noData")))
		return
	}

	data.Name = body.Name
	data.Remark = body.Remark
	data.UpdateBy = reqctx.LoginUserToUserName(c)
	rows := s.neConfigBackupService.Update(data)
	if rows > 0 {
		c.JSON(200, resp.Ok(nil))
		return
	}
	c.JSON(200, resp.Err(nil))
}

// 网元配置文件备份记录删除
//
// DELETE /?id=xx
func (s NeConfigBackupController) Remove(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	id := c.Query("id")
	if id == "" {
		c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "bind err: id is empty"))
		return
	}

	// 处理字符转id数组后去重
	uniqueIDs := parse.RemoveDuplicatesToArray(id, ",")
	// 转换成int64数组类型
	ids := make([]int64, 0)
	for _, v := range uniqueIDs {
		ids = append(ids, parse.Number(v))
	}

	rows, err := s.neConfigBackupService.DeleteByIds(ids)
	if err != nil {
		c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error())))
		return
	}
	msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
	c.JSON(200, resp.OkMsg(msg))
}

// 网元配置文件备份导入
//
// POST /import
func (s NeConfigBackupController) Import(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	var body struct {
		NeType string `json:"neType" binding:"required"`
		NeId   string `json:"neId" binding:"required"`
		Type   string `json:"type" binding:"required,oneof=backup upload"` // 导入类型
		Path   string `json:"path" binding:"required"`                     // 文件路径
	}
	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
	}
	if !strings.HasSuffix(body.Path, ".zip") {
		c.JSON(200, resp.ErrMsg("Only supports decompression of zip files"))
		return
	}

	// 查网元
	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
	}
	// 将zip文件解压到本地后复制到网元端
	localFilePath := body.Path
	if body.Type == "upload" {
		localFilePath = file.ParseUploadFileAbsPath(body.Path)
	}
	if err := s.neConfigBackupService.FileLocalToNe(neInfo, localFilePath); err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}
	c.JSON(200, resp.Ok(nil))
}

// 网元配置文件备份导出
//
// POST /export
func (s NeConfigBackupController) Export(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	var body struct {
		NeType string `json:"neType" binding:"required"`
		NeId   string `json:"neId" binding:"required"`
	}
	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
	}
	// 查网元
	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
	}
	// 将网元文件备份到本地
	zipFilePath, err := s.neConfigBackupService.FileNeToLocal(neInfo)
	if err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}
	// 新增备份记录
	item := model.NeConfigBackup{
		NeType:   neInfo.NeType,
		NeId:     neInfo.NeId,
		Name:     filepath.Base(zipFilePath),
		Path:     zipFilePath,
		CreateBy: reqctx.LoginUserToUserName(c),
	}
	s.neConfigBackupService.Insert(item)
	c.FileAttachment(item.Path, item.Name)
}
