package controller

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"be.ems/src/framework/reqctx"
	"be.ems/src/framework/resp"
	"be.ems/src/framework/utils/file"
	"be.ems/src/modules/ne_data/model"
	"be.ems/src/modules/ne_data/service"

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

// 实例化控制层 BackupController 结构体
var NewBackup = &BackupController{
	backupService: service.NewBackup,
}

// 备份数据
//
// PATH /backup
type BackupController struct {
	backupService *service.Backup // 备份相关服务
}

// 备份文件-更新FTP配置
//
// PUT /ftp
func (s BackupController) FTPUpdate(c *gin.Context) {
	var body model.BackupDataFTP
	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
	}

	byteData, err := json.Marshal(body)
	if err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}

	up := s.backupService.FTPConfigUpdate(string(byteData), reqctx.LoginUserToUserName(c))
	if up <= 0 {
		c.JSON(200, resp.ErrMsg("update failed"))
		return
	}
	c.JSON(200, resp.Ok(nil))
}

// 备份文件-获取FTP配置
//
// GET /ftp
func (s BackupController) FTPInfo(c *gin.Context) {
	info := s.backupService.FTPConfigInfo()
	c.JSON(200, resp.OkData(info))
}

// 备份文件-文件FTP发送
//
// POST /ftp
func (s BackupController) FTPPush(c *gin.Context) {
	var body struct {
		Path     string `form:"path"  binding:"required"` // 路径必须是 BACKUP_DIR 开头的路径
		Filename string `form:"fileName"  binding:"required"`
		Tag      string `form:"tag"  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.HasPrefix(body.Path, s.backupService.BACKUP_DIR) {
		c.JSON(200, resp.ErrMsg("operation path is not within the allowed range"))
		return
	}

	// 判断文件是否存在
	localFilePath := filepath.Join(body.Path, body.Filename)
	if runtime.GOOS == "windows" {
		localFilePath = fmt.Sprintf("C:%s", localFilePath)
	}
	if _, err := os.Stat(localFilePath); os.IsNotExist(err) {
		c.JSON(200, resp.ErrMsg("file does not exist"))
		return
	}

	// 发送文件
	err := s.backupService.FTPPushFile(localFilePath, body.Tag)
	if err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}
	c.JSON(200, resp.Ok(nil))
}

// 备份文件-导入OMC
//
// POST /import-omc
func (s BackupController) ImportOMC(c *gin.Context) {
	var body struct {
		NeType string `json:"neType" binding:"required,oneof=OMC"`
		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
	}

	// 将zip文件解压到本地后复制到网元端
	localFilePath := file.ParseUploadFileAbsPath(body.Path)
	if err := s.backupService.BackupOMCImport(localFilePath); err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}
	c.JSON(200, resp.Ok(nil))
}

// 备份文件-导出OMC
//
// POST /export-omc
func (s BackupController) ExportOMC(c *gin.Context) {
	zipFilePath, err := s.backupService.BackupOMCExport()
	if err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}
	c.FileAttachment(zipFilePath, filepath.Base(zipFilePath))
}
