package service

import (
	"encoding/json"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/admin/forms"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility/character"
	"gadmin/utility/serializer"
	"github.com/gin-gonic/gin"
	"os"
	"time"
)

// Notice 广播
var Notice = new(sNotice)

type sNotice struct{}

func (s *sNotice) List(ctx *gin.Context, req forms.NoticeV2ListReq) serializer.Response {
	type AdminNotice struct {
		model.AdminNotice
		StatusName string `json:"statusName"`
		StatusTag  string `json:"statusTag"`
		TypeName   string `json:"typeName"`
	}
	var (
		q            = query.Use(config.DB).AdminNotice
		m            = q.WithContext(ctx).Where(q.Environment.Eq(os.Getenv("GIN_MODE")))
		offset int64 = 0
		models forms.ListRes
		lists  []*AdminNotice
	)

	m = m.Order(q.ID.Desc())

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	count, err := m.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count > 0 {
		if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		}
	}

	for _, v := range lists {
		v.StatusName = consts.NoticeStatusNameMap[v.Status]
		v.StatusTag = consts.NoticeStatusTagMap[v.Status]
		v.TypeName = consts.NoticeTypeNameMap[v.NoticeType]
	}

	models.List = lists
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = (count + req.PerPage - 1) / req.PerPage

	return serializer.Suc(models)
}

func (s *sNotice) Cancel(ctx *gin.Context, req forms.NoticeV2CancelReq) serializer.Response {
	var (
		q      = query.Use(config.DB).AdminNotice
		models *model.AdminNotice
		err    error
	)

	if req.Id <= 0 {
		return serializer.ParamErr("ID不能空，操作失败！", nil)
	}

	err = query.Use(config.DB).AdminNotice.WithContext(ctx).
		Where(q.ID.Eq(req.Id)).
		Where(q.Environment.Eq(os.Getenv("GIN_MODE"))).Scan(&models)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if models == nil {
		return serializer.DBErr("未找到广播记录", nil)
	}

	if models.Status != consts.NoticeStatusRunning && models.Status != consts.NoticeStatusNotStarted {
		return serializer.ParamErr("广播未在运行，无需终止", nil)
	}

	_, err = query.Use(config.DB).AdminNotice.WithContext(ctx).
		Where(q.ID.Eq(req.Id)).
		Where(q.Environment.Eq(os.Getenv("GIN_MODE"))).
		Updates(&model.AdminNotice{Status: consts.NoticeStatusTerminated, UpdatedAt: time.Now().Unix()})
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	return serializer.Suc(nil)
}

func (s *sNotice) Add(ctx *gin.Context, req forms.NoticeV2AddReq) serializer.Response {
	var (
		q   = query.Use(config.DB).AdminNotice
		err error
	)

	serverIds, _ := json.Marshal(req.ServerIds)

	// 编辑
	if req.Id > 0 {
		notice := model.AdminNotice{
			Environment:  os.Getenv("GIN_MODE"),
			ServerIds:    string(serverIds),
			NoticeType:   req.NoticeType,
			Content:      req.Content,
			SendInterval: req.SendInterval,
			StartAt:      req.StartAt,
			EndAt:        req.EndAt,
			UpdatedAt:    time.Now().Unix(),
		}

		if req.StartAt > time.Now().Unix() {
			notice.Status = consts.NoticeStatusNotStarted
		}
		if _, err = query.Use(config.DB).AdminNotice.WithContext(ctx).
			Where(q.ID.Eq(req.Id)).
			Where(q.Environment.Eq(os.Getenv("GIN_MODE"))).
			Updates(&notice); err != nil {
			return serializer.DBErr(err.Error(), err)
		}

		return serializer.Suc(nil)
	}

	// 新增
	notice := &model.AdminNotice{
		Environment:  os.Getenv("GIN_MODE"),
		MsgID:        character.GenerateMsgId(),
		ServerIds:    string(serverIds),
		NoticeType:   req.NoticeType,
		Content:      req.Content,
		SendInterval: req.SendInterval,
		StartAt:      req.StartAt,
		EndAt:        req.EndAt,
		Status:       consts.NoticeStatusRunning,
		UpdatedAt:    time.Now().Unix(),
		CreatedAt:    time.Now().Unix(),
	}
	if req.StartAt > time.Now().Unix() {
		notice.Status = consts.NoticeStatusNotStarted
	}
	if err = query.Use(config.DB).AdminNotice.WithContext(ctx).Create(notice); err != nil {
		return serializer.DBErr(err.Error(), err)
	}
	return serializer.Suc(nil)
}
