package api

import (
	"gitee.ltd/lxh/logger/log"
	"github.com/gin-gonic/gin"
	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
	"wireguard-dashboard/command"
	"wireguard-dashboard/http/param"
	"wireguard-dashboard/model/entity"
	"wireguard-dashboard/queues"
	"wireguard-dashboard/repository"
	"wireguard-dashboard/utils"
)

type server struct{}

func Server() server {
	return server{}
}

// SaveServer
// @description: 新增/更新服务端信息
// @receiver server
// @param c
func (server) SaveServer(c *gin.Context) {
	var p param.SaveServer
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	var err error
	var serverId string
	if p.Id != "" {
		serverId = p.Id
		if err = repository.Server().Update(p); err != nil {
			log.Errorf("更改服务端信息失败: %v", err.Error())
		}
	} else {
		privateKey, err := wgtypes.GeneratePrivateKey()
		if err != nil {
			utils.GinResponse(c).FailedWithMsg("生成密钥失败")
			return
		}
		publicKey := privateKey.PublicKey()
		serverInfo := &entity.Server{
			IpScope:        p.IpScope,
			ListenPort:     p.ListenPort,
			PrivateKey:     privateKey.String(),
			PublicKey:      publicKey.String(),
			PostUpScript:   p.PostUpScript,
			PreDownScript:  p.PreDownScript,
			PostDownScript: p.PostDownScript,
		}
		if err = repository.Server().Save(serverInfo); err != nil {
			log.Errorf("新增服务端失败: %v", err.Error())
		}

		serverId = serverInfo.Id
	}

	if err != nil {
		utils.GinResponse(c).FailedWithMsg("操作失败")
		return
	}

	go func() {
		if err = queues.PutAsyncWireguardConfigFile(serverId); err != nil {
			log.Errorf("[新增/编辑]投递同步配置文件任务失败: %s", err.Error())
		}
	}()

	utils.GinResponse(c).OK()
}

// GetServer
// @description: 获取服务端信息
// @receiver wireguard
// @param c
func (server) GetServer(c *gin.Context) {
	data, err := repository.Server().GetServer()
	if err != nil {
		log.Errorf("获取服务端信息失败: %v", err.Error())
	}

	utils.GinResponse(c).OKWithData(data)
}

// ControlServer
// @description: 服务端控制器
// @receiver server
// @param c
func (server) ControlServer(c *gin.Context) {
	var p param.ControlServer
	if err := c.ShouldBind(&p); err != nil {
		utils.GinResponse(c).FailedWithErr("参数错误", err)
		return
	}

	switch p.Status {
	case "START":
		command.StartWireguard()
	case "STOP":
		command.StopWireguard()
	case "RESTART":
		command.RestartWireguard(false)
	}

	utils.GinResponse(c).OK()
}
