package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.ltd/lxh/logger/log"
	"github.com/gin-gonic/gin"
	"os"
	"slices"
	"wireguard-ui/component"
	"wireguard-ui/http/param"
	"wireguard-ui/http/response"
	"wireguard-ui/http/vo"
	"wireguard-ui/model"
	"wireguard-ui/script"
	"wireguard-ui/service"
	"wireguard-ui/utils"
)

type setting struct{}

func Setting() setting {
	return setting{}
}

// Set
// @description: 设置配置
// @receiver setting
// @param c
func (setting) Set(c *gin.Context) {
	var p param.SetSetting
	if err := c.ShouldBind(&p); err != nil {
		response.R(c).Validator(err)
		return
	}

	if err := service.Setting().SetData(&model.Setting{
		Code:     p.Code,
		Data:     p.Data,
		Describe: p.Describe,
	}); err != nil {
		response.R(c).FailedWithError(err)
		return
	}

	var whiteCodes = []string{"WG_SETTING", "WG_SERVER"}
	if slices.Contains(whiteCodes, p.Code) {
		go func() {
			if err := script.New().GenerateConfig(); err != nil {
				log.Errorf("执行脚本失败")
			}
		}()
	}

	response.R(c).OK()
}

// Delete
// @description: 删除配置
// @receiver setting
// @param c
func (setting) Delete(c *gin.Context) {
	code := c.Param("code")
	if code == "" || code == "undefined" {
		response.R(c).FailedWithError("code不能为空")
		return
	}

	if err := service.Setting().Model(&model.Setting{}).Where("code NOT IN (?)", []string{"WG_SETTING", "WG_SERVER"}).Where("code = ?", code).Delete(&model.Setting{}).Error; err != nil {
		response.R(c).FailedWithError("删除失败")
		return
	}

	response.R(c).OK()
}

// GetSetting
// @description: 获取指定配置
// @receiver setting
// @param c
func (setting) GetSetting(c *gin.Context) {
	code := c.Query("code")
	if code == "" {
		response.R(c).FailedWithError("code不能为空")
		return
	}

	var data *model.Setting
	if err := service.Setting().Model(&model.Setting{}).Where("code = ?", code).Take(&data).Error; err != nil {
		response.R(c).FailedWithError("获取指定配置失败")
		return
	}

	response.R(c).OkWithData(data.Data)
}

// GetAllSetting
// @description: 获取全部配置
// @receiver setting
// @param c
func (setting) GetAllSetting(c *gin.Context) {
	// 不查询的配置
	var blackList = []string{"WG_SETTING", "WG_SERVER"}

	data, err := service.Setting().GetAllSetting(blackList)
	if err != nil {
		response.R(c).FailedWithError("获取配置失败")
		return
	}

	response.R(c).OkWithData(data)
}

// GetPublicAddr
// @description: 获取公网地址
// @receiver setting
// @param c
func (setting) GetPublicAddr(c *gin.Context) {
	response.R(c).OkWithData(utils.Network().GetHostPublicIP())
}

// Export
// @description: 导出配置
// @receiver setting
// @param c
func (setting) Export(c *gin.Context) {
	// 获取当前登陆用户
	var loginUser *vo.User
	if loginUser = GetCurrentLoginUser(c); c.IsAborted() {
		return
	}

	if loginUser.Account != "admin" {
		response.R(c).FailedWithError("非法操作，你被捕啦！")
		return
	}

	// 获取配置
	data, err := service.Setting().Export()
	if err != nil {
		response.R(c).FailedWithError(err)
		return
	}

	// 生成配置文件
	dataBytes, _ := json.Marshal(data)
	filepath, err := utils.FileUtils().GenerateFile("config.json", dataBytes)
	if err != nil {
		response.R(c).FailedWithError(err)
		return
	}

	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename="+filepath)
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Connection", "keep-alive")
	c.File(filepath)
	if err = os.Remove(filepath); err != nil {
		log.Errorf("删除临时文件失败: %s", err.Error())
	}
}

// Import
// @description: 导入配置
// @receiver setting
// @param c
func (setting) Import(c *gin.Context) {
	var p param.Import
	if err := c.ShouldBind(&p); err != nil {
		response.R(c).Validator(err)
		return
	}

	// 校验文件是否合规
	if p.File.Filename != "config.json" {
		response.R(c).Validator(errors.New("文件名不合规"))
		return
	}

	// 校验文件内容是否符合
	fileBytes, err := p.File.Open()
	if err != nil {
		response.R(c).FailedWithError(err)
		return
	}
	defer func() {
		_ = fileBytes.Close()
	}()

	var data vo.Export
	if err := json.NewDecoder(fileBytes).Decode(&data); err != nil {
		response.R(c).FailedWithError(err)
		return
	}

	// 校验json串是否合规
	if err = component.Validate(&data); err != nil {
		response.R(c).Validator(err)
		return
	}

	// 获取当前登陆用户
	var loginUser *vo.User
	if loginUser = GetCurrentLoginUser(c); c.IsAborted() {
		return
	}

	if loginUser.Account != "admin" {
		response.R(c).FailedWithError("非法操作，你被捕啦！")
		return
	}

	if err = service.Setting().Import(&data, loginUser); err != nil {
		response.R(c).FailedWithError(fmt.Errorf("导入失败: %v", err.Error()))
		return
	}

	response.R(c).OK()
}
