package v1

import (
	"cmdb-backend/models"
	"cmdb-backend/pkg/utils"
	"cmdb-backend/providers"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"
)

type OpDnsRecordReq struct {
	Id        int    `json:"id"`
	RecordId  int64  `json:"record_id"`
	RecordIds []int  `json:"record_ids"` //批量修改 owner 专用字段
	ZoneId    int    `json:"zone_id"`
	ZoneName  string `json:"zone_name"`
	VendorId  int    `json:"vendor_id"`
	Name      string `json:"name"`
	Type      string `json:"type"`
	Line      string `json:"line"`
	Ttl       int    `json:"ttl"`
	Target    string `json:"target"`
	Status    string `json:"status"` /*enable,disable*/
	Owner     string `json:"owner"`
	Remark    string `json:"remark"`
}

func GetDnsZoneList(c *gin.Context) {
	vendorId, _ := strconv.Atoi(c.Query("vendor_id"))
	resp := utils.SelectResponse{
		Options: []utils.SelectOption{},
	}
	options := map[string]utils.SelectOption{}

	dnsZones := models.GetDnsZones(vendorId)
	for _, zone := range dnsZones {
		options[zone] = utils.SelectOption{
			Label: zone,
			Value: zone,
		}
	}

	for _, option := range options {
		resp.Options = append(resp.Options, option)
	}
	sort.Sort(resp.Options)

	c.JSON(http.StatusOK, utils.AmisResponse{
		Data: resp,
	})
}

func GetDnsTypeList(c *gin.Context) {
	resp := utils.SelectResponse{
		Options: []utils.SelectOption{},
	}
	options := map[string]utils.SelectOption{}

	dnsTypes := models.GetDnsTypes()
	for _, dnsType := range dnsTypes {
		options[dnsType] = utils.SelectOption{
			Label: dnsType,
			Value: dnsType,
		}
	}

	for _, option := range options {
		resp.Options = append(resp.Options, option)
	}
	sort.Sort(resp.Options)

	c.JSON(http.StatusOK, utils.AmisResponse{
		Data: resp,
	})
}

func GetDnsRecord(c *gin.Context) {
	// 从 session 获取当前登录用户
	email := sessions.Default(c).Get("email")
	currentUser := strings.Split(email.(string), "@")[0]

	key := c.Query("key")
	isMine := c.Query("is_mine")
	recordType := c.Query("type")
	zoneName := c.Param("zone_name")
	pageNum, _ := strconv.Atoi(c.Query("page_number"))
	pageSize, _ := strconv.Atoi(c.Query("page_size"))

	status := models.ExitDnsZoneByName(zoneName)
	if !status {
		utils.AmisError(c, "要查询解析的域名不存在!")
		return
	}

	records := models.GetDnsRecord(zoneName, recordType, key, isMine, utils.GetPage(pageNum, pageSize), pageSize, currentUser)
	total := models.GetDnsRecordTotal(zoneName, recordType, key, isMine, currentUser)

	c.JSON(http.StatusOK, utils.AmisResponse{
		Data: map[string]interface{}{
			"items": records,
			"total": total,
		},
	})
}

func CreateDnsRecord(c *gin.Context) {
	query := OpDnsRecordReq{}
	if err := c.ShouldBindJSON(&query); err != nil {
		utils.AmisError(c, "数据类型不正确，请修改后重新提交。")
		return
	}

	//判断记录值是否合法
	if err := utils.CheckDnsRecordValue(query.Type, query.Target); err != nil {
		utils.AmisError(c, err)
		return
	}

	//查询 zone_name 所属厂商，调对应的 API 操作，仅支持 腾讯 DNSPod(5)、Godaddy(9)
	zoneName := c.Param("zone_name")
	vendorId := models.GetDnsVendorByName(zoneName)
	if vendorId == 5 {
		recordId, err := providers.TencentCreateDnsRecord(
			query.ZoneName, query.Name, query.Type, query.Line, query.Target, query.Ttl, query.Status)
		if err != nil {
			utils.AmisError(c, err)
			return
		}
		query.RecordId = recordId
	} else if vendorId == 9 {
		//TODO: 实现 Godaddy 厂商增删改查
	} else {
		utils.AmisError(c, "找不到此域名，请检查域名是否正确。")
		return
	}

	//保存到数据库
	currentTime := time.Now().Format("2006-01-02 15:04:05")
	dnsRecord := &models.DnsRecord{
		Name:       query.Name,
		RecordId:   query.RecordId,
		ZoneName:   query.ZoneName,
		ZoneId:     query.ZoneId,
		VendorId:   vendorId,
		Type:       query.Type,
		Line:       query.Line,
		Ttl:        query.Ttl,
		Target:     query.Target,
		Status:     query.Status,
		Owner:      query.Owner,
		Remark:     query.Remark,
		CreateTime: utils.Str2Time(currentTime),
		UpdateTime: utils.Str2Time(currentTime),
	}
	if err := models.CreateDnsRecord(dnsRecord); err != nil {
		utils.AmisError(c, "create dns record failed !")
		return
	}

	c.JSON(http.StatusOK, utils.AmisResponse{
		Msg: "域名添加成功，预计 10 分钟生效。",
	})
}

// UpdateDnsRecord 用于更新 DNS 记录 (单条或批量)
func UpdateDnsRecord(c *gin.Context) {
	query := OpDnsRecordReq{}
	if err := c.ShouldBindJSON(&query); err != nil {
		utils.AmisError(c, "数据格式不正确，请修改后重新提交。")
		return
	}

	// 检查记录值是否合法 (A 记录、CNAME 记录、TXT 记录...)
	if err := utils.CheckDnsRecordValue(query.Type, query.Target); err != nil {
		utils.AmisError(c, err)
		return
	}

	// 批量修改 owner 复用此接口，但是只有一条选中的记录，才能修改其他字段, 选中一条 RecordIds 为 [0]
	if len(query.RecordIds) == 0 {
		//查询 zone_name 所属厂商，调对应的 API 操作，出于安全合规考虑，仅支持腾讯 DNSPod(5)
		zoneName := c.Param("zone_name")
		vendorId := models.GetDnsVendorByName(zoneName)
		if vendorId == 5 {
			err := providers.TencentUpdateDnsRecord(
				query.ZoneName, query.Name, query.Type, query.Line, query.Target, query.Ttl, query.RecordId)
			if err != nil {
				utils.AmisError(c, err)
				return
			}
		} else {
			utils.AmisError(c, "不支持修改非腾讯 DNSPod 管理的 DNS, 如有需求请在 Ask CMDB 话题群咨询。")
			return
		}
	}

	//更新数据库
	if err := models.UpdateDnsRecords(query.Id, query.Name, query.Type, query.Target, query.Ttl,
		query.Line, query.Owner, query.Remark, query.RecordIds); err != nil {
		utils.AmisError(c, "update dns record failed !")
		return
	}

	c.JSON(http.StatusOK, utils.AmisResponse{
		Msg: "域名修改成功，预计 10 分钟生效。",
	})
}

func DeleteDnsRecord(c *gin.Context) {
	query := OpDnsRecordReq{}
	if err := c.ShouldBindJSON(&query); err != nil {
		utils.AmisError(c, "数据格式不正确，请修改后重新提交。")
		return
	}

	//查询 zone_name 所属厂商，调对应的 API 操作，仅支持 腾讯 DNSPod(5)
	zoneName := c.Param("zone_name")
	vendorId := models.GetDnsVendorByName(zoneName)
	if vendorId == 5 {
		err := providers.TencentDeleteDnsRecord(query.ZoneName, query.RecordId)
		if err != nil {
			utils.AmisError(c, err)
			return
		}
	} else {
		utils.AmisError(c, "找不到此记录，请检查后重新提交。")
		return
	}

	err := models.DeleteDnsRecord(query.Id)
	if err != nil {
		utils.AmisError(c, "delete dns record failed !")
		return
	}

	c.JSON(http.StatusOK, utils.AmisResponse{
		Msg: "域名删除成功。",
	})
}

func DisableDnsRecord(c *gin.Context) {
	query := OpDnsRecordReq{}
	if err := c.ShouldBindJSON(&query); err != nil {
		utils.AmisError(c, "数据格式不正确，请修改后重新提交。")
		return
	}

	//查询 zone_name 所属厂商，调对应的 API 操作，仅支持 腾讯 DNSPod(5)
	zoneName := c.Param("zone_name")
	vendorId := models.GetDnsVendorByName(zoneName)
	if vendorId == 5 {
		err := providers.TencentModifyRecordStatus(query.ZoneName, query.RecordId, query.Status)
		if err != nil {
			utils.AmisError(c, err)
			return
		}
	} else {
		utils.AmisError(c, "只有腾讯 dnsPod 记录支持暂停解析操作。")
		return
	}

	if err := models.UpdateDnsRecordStatus(query.Id, query.Status); err != nil {
		utils.AmisError(c, "update dns record status failed !")
		return
	}

	c.JSON(http.StatusOK, utils.AmisResponse{
		Msg: "域名暂停解析成功。",
	})
}

func EnableDnsRecord(c *gin.Context) {
	query := OpDnsRecordReq{}
	if err := c.ShouldBindJSON(&query); err != nil {
		utils.AmisError(c, "数据格式不正确，请修改后重新提交。")
		return
	}

	//查询 zone_name 所属厂商，调对应的 API 操作，仅支持 腾讯 DNSPod(5)
	zoneName := c.Param("zone_name")
	vendorId := models.GetDnsVendorByName(zoneName)
	if vendorId == 5 {
		err := providers.TencentModifyRecordStatus(query.ZoneName, query.RecordId, query.Status)
		if err != nil {
			utils.AmisError(c, err)
			return
		}
	} else {
		utils.AmisError(c, "只有腾讯 dnsPod 记录支持恢复解析操作。")
		return
	}

	if err := models.UpdateDnsRecordStatus(query.Id, query.Status); err != nil {
		utils.AmisError(c, "update dns record status failed !")
		return
	}

	c.JSON(http.StatusOK, utils.AmisResponse{
		Msg: "域名恢复解析成功。",
	})
}
