package gm_services

import (
	"errors"
	"gadmin/internal/admin/forms"
	"gadmin/internal/admin/gmdb/filedb"
	"github.com/sirupsen/logrus"
	"os"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/jinzhu/copier"
	"github.com/jinzhu/now"
	"github.com/robfig/cron/v3"
)

var (
	emailDB *filedb.Collection
	// EmailsPool = forms.EmailList{}
	duration = 5 * time.Minute
	cronTab  *cron.Cron
	lock     sync.Mutex
)

func getEmailDB() *filedb.Collection {
	if emailDB != nil {
		return emailDB
	}
	emailDB = InitDb()
	return emailDB
}

func InitDb() *filedb.Collection {
	db := filedb.NewCollection(os.Getenv("STORAGE_EMAILS"))
	if err := db.LoadDb(); err != nil {
		logrus.Error("emailDB InitDb err:", err)
		return nil
	}
	return db
}

func SaveEmailDb() {
	if err := getEmailDB().SaveDb(); err != nil {
		logrus.Error("emailDB SaveDb err:", err)
		return
	}
}

func EmailCron() {
	cronTab = cron.New()
	cronTab.AddFunc("*/1 * * * *", timerSendLetter)
	cronTab.AddFunc("*/1 * * * *", SaveEmailDb)
	go cronTab.Run()
}

func timerSendLetter() {
	contents, _ := getEmailDB().All()
	// contents := EmailsPool
	now := time.Now().Unix()
	for _, v := range contents {
		if item, ok := v.(*forms.EmailItem); ok {
			if item.Deleted || item.Opt != "send" {
				continue
			}
			if item.SentAt == 0 && item.SendAt >= now-int64(duration) && item.SendAt <= now {
				// sendEmail
				logrus.WithField("from", "timerSendLetter").Infoln(item)
				err := sendLetterToWorld(item)
				if err != nil {
					logrus.Error("emailDB sendLetterToWorld err:", err)
					return
				}
			}
		}

	}
}

func GetEmails(page, perPage int) (emails []*forms.EmailItem, total int, err error) {
	mails, _ := getEmailDB().All()
	contents := forms.EmailList{}
	for _, v := range mails {
		contents = append(contents, v.(*forms.EmailItem))
	}
	// page, perPage = 1, 100000

	sort.Sort(contents)
	total = len(contents)
	if total >= page*perPage {
		emails = contents[(page-1)*perPage : page*perPage]
	} else if total > (page-1)*perPage {
		emails = contents[(page-1)*perPage:]
	}

	return
}

func DeleteEmail(id int64) (err error) {
	if id > 0 {
		mail, err := getEmailDB().Find(id)
		if err == nil {
			if v, ok := mail.(*forms.EmailItem); ok {
				v.Status = "已删除"
				if err = getEmailDB().Add(v); err != nil {
					logrus.Error("emailDB Add err:", err)
					return err
				}
			}
		}

	} else {
		err = errors.New("ID不能为0")
	}
	return
}

// AddEmails 添加邮件 存草稿|发送|删除
// 只能删除草稿箱里的，
func AddEmails(params *forms.EmailItemReq) (*forms.EmailItem, error) {
	lock.Lock()
	defer lock.Unlock()
	var row = new(forms.EmailItem)
	row.OperatorId = params.OperatorId
	if params.Id > 0 {
		mail, err := getEmailDB().Find(params.Id)
		if err != nil {
			return nil, err
		}
		if email, ok := mail.(*forms.EmailItem); ok {
			row = email
			copier.Copy(row, params)
			row.Title = strings.ReplaceAll(params.Title, "%", "")
			row.Content = strings.ReplaceAll(params.Content, "%", "")
			if email.Status == "已发送" || email.Status == "已删除" {
				return nil, errors.New("邮件状态无法编辑")
			}
		}
	} else {
		copier.Copy(row, params)
		row.Title = strings.ReplaceAll(params.Title, "%", "")
		row.Content = strings.ReplaceAll(params.Content, "%", "")
	}

	if params.Opt != "draft" {
		if params.SendWay == 1 {
			row.SendAt = time.Now().Unix()
		} else {
			if params.SendAt == "" {
				return nil, errors.New("发送时间不能为空")
			}
			stamp, _ := now.Parse(params.SendAt)
			row.SendAt = stamp.Unix()
			row.Status = "待发送"
			if row.SendAt == 0 {
				return nil, errors.New("发送时间不能为空")
			}
		}
	} else {
		if row.Status != "" {
			return nil, errors.New("邮件状态无法编辑")
		}
		if params.SendWay == 1 {
			row.SendAt = time.Now().Unix()
		} else {
			stamp, _ := now.Parse(params.SendAt)
			row.SendAt = stamp.Unix()
		}
	}

	err := getEmailDB().Add(row)

	if err != nil {
		return row, err
	}

	switch params.Opt {
	case "draft":
		// 存草稿
	case "send":
		// 发送邮件
		err = sendMail(row)
	}
	return row, err
}

func sendMail(params *forms.EmailItem) (err error) {
	if params.SendWay == 1 {
		//  // 1 立即发送 0 待发送
		if err = sendLetterToWorld(params); err != nil {
			logrus.Error("emailDB sendLetterToWorld err:", err)
			return err
		}

		if err = getEmailDB().Add(params); err != nil {
			logrus.Error("emailDB Add err:", err)
			return err
		}
	}
	return
}

func sendLetterToWorld(params *forms.EmailItem) (err error) {
	/*var letter model.GlobalLetter

	copier.Copy(&letter, params)
	letter.Extra = makeExtData(params)
	letter.Type = 6
	letter.CreateTime = time.Now()
	letter.ExpireTime = time.Now().AddDate(0, 0, params.Expired)

	var (
		players   []int64
		serverIds []int
	)

	serverIds = service.ServerOption.GetServerIds()

	switch params.RecieverType {
	case 1: // 全服
		msg := msg2.GMLetter{
			MsgId:      character.GenerateMsgId(),
			Letter:     &letter,
			Players:    players,
			OperatorId: params.OperatorId,
		}

		rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功,全服投递",
			utility.FormatSecond(time.Now()),
			params.Id)

		for _, serverId := range serverIds {
			DB, err := player.GetDBByServerID(serverId)
			if err != nil {
				logrus.Warnf("sendLetterToWorld GetDBByServerID err:%+v", err)
				continue
			}

			var resp *msg2.ResponseGMLetter
			res, err := config.GmNats.GmRequest(DB, "GMLetter", msg)
			if err != nil {
				logrus.Warnf("sendLetterToWorld GmRequest err:%+v", err)
				continue
			}

			if err = json.Unmarshal(res, &resp); err != nil {
				logrus.Warnf("sendLetterToWorld nats Unmarshal err:%+v", err)
				continue
			}

			rpc_share.LogChan <- rpc_share.LogMsg{
				MsgID: msg.MsgId,
				Data:  resp,
			}
		}
	case 2: // 指定服

		serverIds := strings.Split(params.Recievers, ",")
		for _, serverId := range serverIds {
			sId := cast.ToInt(serverId)
			if sId > 0 {
				DB, err := player.GetDBByServerID(sId)
				if err != nil {
					logrus.Warnf("sendLetterToWorld2 GetDBByServerID2 err:%+v", err)
					continue
				}

				msg := msg2.GMLetter{
					MsgId:      character.GenerateMsgId(),
					Letter:     &letter,
					Players:    players,
					OperatorId: params.OperatorId,
				}

				rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功,投递服务器ID:%v",
					utility.FormatSecond(time.Now()), params.Id, sId)

				var resp *msg2.ResponseGMLetter
				res, err := config.GmNats.GmRequest(DB, "GMLetter", msg)
				if err != nil {
					logrus.Warnf("sendLetterToWorld2 GmRequest err:%+v", err)
					continue
				}

				if err = json.Unmarshal(res, &resp); err != nil {
					logrus.Warnf("sendLetterToWorld2 nats Unmarshal err:%+v", err)
					continue
				}

				rpc_share.LogChan <- rpc_share.LogMsg{
					MsgID: msg.MsgId,
					Data:  resp,
				}
			}
		}
	case 3: // 指定玩家
		data := strings.Split(params.Recievers, ",")
		for _, v := range data {
			playerID := cast.ToInt64(v)
			if playerID > 0 {
				DB, err := player.GetDBByUserId(playerID)
				if err != nil {
					logrus.Warnf("sendLetterToWorld3 GetDBByUserId err:%+v", err)
					continue
				}

				msg := msg2.GMLetter{
					MsgId:      character.GenerateMsgId(),
					Letter:     &letter,
					Players:    []int64{playerID},
					OperatorId: params.OperatorId,
				}

				rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功,投递玩家ID:%v",
					utility.FormatSecond(time.Now()), params.Id, playerID)

				var resp *msg2.ResponseGMLetter
				res, err := config.GmNats.GmRequest(DB, "GMLetter", msg)
				if err != nil {
					logrus.Warnf("sendLetterToWorld3 GmRequest err:%+v", err)
					continue
				}

				if err = json.Unmarshal(res, &resp); err != nil {
					logrus.Warnf("sendLetterToWorld3 nats Unmarshal err:%+v", err)
					continue
				}

				rpc_share.LogChan <- rpc_share.LogMsg{
					MsgID: msg.MsgId,
					Data:  resp,
				}

			}
		}
	}

	//if params.Recievers != "全员" {
	//	data := strings.Split(params.Recievers, ",")
	//	for _, v := range data {
	//		playerID := cast.ToInt64(v)
	//		if playerID > 0 {
	//			players = append(players, playerID)
	//		}
	//	}
	//}
	//msg := msg2.GMLetter{
	//	MsgId:      character.GenerateMsgId(),
	//	Letter:     &letter,
	//	Players:    players,
	//	OperatorId: params.OperatorId,
	//}
	//
	//err = gate.SendToWorld(0, &msg)
	//if err == nil {
	//	rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功",
	//		utility.FormatSecond(time.Now()),
	//		params.Id)
	//}
	params.Status = "已发送"
	params.SentAt = time.Now().Unix()*/
	return
}

/*func makeExtData(params *forms.EmailItem) (data model.ExtraData) {
	var dim int64 = 1000000 //60306070
	for _, v := range params.Ext {
		uid := cast.ToInt64(v.Id)
		count := cast.ToInt(v.Count)
		if uid > dim {
			for i := 0; i < count; i++ {
				data.Equips = append(data.Equips, uid)
			}
		} else if uid > 0 {
			data.Materials = append(data.Materials, &model.DropMaterial{ID: uid, Count: count})
		}
	}
	return
}*/
