package game

import (
	"encoding/json"
	"math"
	"server/MergeConst"
	"server/conf"
	champshipCfg "server/conf/champship"
	chargeCfg "server/conf/charge"
	languageCfg "server/conf/language"
	mailCfg "server/conf/mail"
	mergeDataCfg "server/conf/merge_data"
	"server/db"
	"server/game/mod/chess"
	"server/game/mod/item"
	"server/game/mod/mail"
	"server/game/mod/order"
	"server/game/mod/quest"
	GoUtil "server/game_util"
	"server/msg"
	"server/pkg/github.com/name5566/leaf/log"
	"sort"
)

const (
	TRIGGER_PARAM_LV  = "lv"  // 等级
	TRIGGER_PARAM_REQ = "reg" // 注册天数
)

func (player *Player) MailTrigger(Tr *quest.Trigger) bool {
	MailMod := player.PlayMod.getMailMod()
	TriggerMail := mailCfg.GetTriggerMail()
	t := make([]*mailCfg.TriggerMail, 0, len(TriggerMail))
	for _, v := range TriggerMail {
		if GoUtil.InArray(v.Id, MailMod.TriggerMail) {
			continue
		}
		if Tr.Label != v.Trigger[0] {
			continue
		}
		t = append(t, v)
	}
	if len(t) == 0 {
		return false
	}
	tr := false
	for _, v := range t {
		if player.checkTriggerCondition(v.Trigger) {
			Title := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, v.Title)
			Content := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, v.Content)
			TitleEn := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, v.Title)
			ContentEn := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, v.Content)
			TitlePtBr := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_PTBR, v.Title)
			ContentPtBr := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_PTBR, v.Content)
			TitleEsLatam := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_ES_LATAM, v.Title)
			ContentEsLatam := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_ES_LATAM, v.Content)
			MailMod.SendMail(&mail.MailStruct{
				Title:           Title,
				SubTitle:        "",
				Content:         Content,
				TitleEn:         TitleEn,
				SubTitleEn:      "",
				ContentEn:       ContentEn,
				TitlePtBr:       TitlePtBr,
				SubTitlePtBr:    "",
				ContentPtBr:     ContentPtBr,
				TitleEsLatam:    TitleEsLatam,
				SubTitleEsLatam: "",
				ContentEsLatam:  ContentEsLatam,
				Items:           v.Items,
				Type:            v.Type,
			})
			MailMod.AddTriggerMail(v.Id)
			tr = true
		}
	}

	return tr
}

func (player *Player) checkTriggerCondition(Trigger []string) bool {
	if len(Trigger) < 4 {
		return false
	}
	switch Trigger[1] {
	case TRIGGER_PARAM_LV:
		lv := player.PlayMod.getBaseMod().GetLevel()
		return GoUtil.Compare(lv, Trigger[2], GoUtil.Int(Trigger[3]))
	case TRIGGER_PARAM_REQ:
		reg := player.GetPlayerBaseMod().GetRegisterTime()
		Day := GoUtil.DaysSince(reg)
		return GoUtil.Compare(Day, Trigger[2], GoUtil.Int(Trigger[3]))
	default:
		return false
	}
}

func (player *Player) TriggerShippingOrderOrigin(req *msg.ReqShippingOrder) {
	OrderSn := req.OrderSn
	Status := int(req.Status)
	if Status == MergeConst.ORDER_STATUS_CANCEL { // 取消支付
		player.CancelOrder(OrderSn)
		player.PushClientRes(&msg.ResShippingOrder{
			Code: msg.RES_CODE_SUCCESS,
			Msg:  "cancel success",
		})
		return
	}
	var err error
	OrderData, err := db.GetPlayerChargeData(OrderSn)
	if err != nil {
		log.Debug("charge shipping GetPlayerChargeData err:%v", err)
		return
	}
	if OrderData.PayStatus == MergeConst.ORDER_STATUS_SHIP {
		log.Debug("charge shipping order already shipped OrderSn:%s", OrderSn)
		return
	}
	log.Debug("[order verify success] Uid:%d;OrderSn:%s;PayOrder:%s;Token:%s", player.M_DwUin, OrderData.OrderId, OrderData.PayChannelOrderId, req.Token)
	player.lock.Lock()
	defer player.lock.Unlock()
	OrderExtraData := &ChargeExtra{}
	if OrderData.PayChannelExtra != "" {
		err = json.Unmarshal([]byte(OrderData.PayChannelExtra), OrderExtraData)
		if err != nil {
			log.Debug("GoogleVerify err:%v", err)
			return
		}
		OrderExtraData.ChargeId = OrderData.ProductId
	}
	if OrderExtraData.Type == 0 {
		player.Charge(int(OrderData.ProductId))
	} else {
		player.SendCharge(OrderExtraData)
	}
	OrderData.PayStatus = MergeConst.ORDER_STATUS_SHIP
	OrderData.ProductName = req.ProduceId
	db.UpdatePlayerChargeData(OrderData)
	player.PlayMod.save()
	if conf.Server.GameName == "Merge_Pet_online" {
		ChargeMod := player.PlayMod.getChargeMod()
		ProduceName := chargeCfg.GetProduceName(OrderData.ProductId)
		GoUtil.SendFeishuOrder(int(player.M_DwUin), OrderData.PayChannelOrderId, OrderData.Price, ProduceName, OrderData.PayTime, GoUtil.Now(), ChargeMod.Charge)
	}
	BaseMod := player.PlayMod.getBaseMod()
	orderDataMap := map[string]interface{}{
		"AppId":             conf.Server.AppID,
		"ServerId":          conf.Server.ServerID,
		"OrderId":           OrderData.OrderId,
		"PayChannelOrderId": OrderData.PayChannelOrderId,
		"ProductId":         OrderData.ProductId,
		"CreateTime":        OrderData.CreateTime,
		"PayTime":           OrderData.PayTime,
		"Token":             req.Token,
		"Price":             OrderData.Price,
		"PayType":           OrderData.PayType,
		"Level":             BaseMod.GetLevel(),
		"Energy":            BaseMod.GetEnergy(),
		"Star":              BaseMod.GetStar(),
	}
	player.TeLog("pay", orderDataMap)
	player.PushClientRes(&msg.ResShippingOrder{
		Code: msg.RES_CODE_SUCCESS,
	})
	player.SendClientRes()
}

func (player *Player) TriggerShippingOrder(req *msg.ReqShippingOrder) {

}

func (p *Player) TriggerComfortOrder() {
	BaseMod := p.PlayMod.getBaseMod()
	Now := GoUtil.Now()
	Lv := BaseMod.GetLevel()

	if Now-BaseMod.GetLogoutTime() < 7*86400 || Lv < 23 {
		return
	}
	OrderMod := p.PlayMod.getOrderMod()
	ChessMod := p.PlayMod.getChessMod()
	OrderMod.ComfortEndTime = int(Now + 86400)
	EmitList := ChessMod.GetEmitList()
	EnergyMul := BaseMod.GetEnergyMul()
	OrderMod.CreateNormalOrder(BaseMod.GetLevel(), EmitList, EnergyMul, order.COMFORT_TYPE)
}

func (p *Player) TriggerSeed() {
	ChampshipMod := p.PlayMod.getChampshipMod()
	Items, Score := champshipCfg.GetRewardItems(ChampshipMod.Reward + 1)
	if Score < 50 {
		return
	}
	b := false
	for _, v := range Items {
		if v.Id == item.ITEM_ENERGY_ID {
			b = true
			break
		}
	}
	BaseMod := p.PlayMod.getBaseMod()
	BaseMod.SetSeed(b)
}

func (p *Player) TriggerSeedSource() {
	BaseMod := p.PlayMod.getBaseMod()
	if !BaseMod.GetSeed() {
		return
	}
	Total := BaseMod.GetEnergy()

	ChessMod := p.PlayMod.getChessMod()
	ChessList := ChessMod.GetUnlockChessList()
	ChessBuff := ChessMod.GetChessBuf()
	AllChess := append(ChessList, ChessBuff...)
	for _, v := range AllChess {
		ChessColor := mergeDataCfg.GetColorById(v)
		if ChessColor == "Energy" {
			Total += mergeDataCfg.GetSellNumById(v)
		}
		if v == chess.CHESS_ENERGY_CHEST {
			Total += 50
		}
		if v == chess.CHESS_SURPRISE_CHEST_LOCK || v == chess.CHESS_SURPRISE_CHEST {
			Total += 10
		}
		if v == chess.CHESS_SOURCE_CHEST {
			Total += 100
		}
		if v == chess.CHESS_HIGH_SOURCE_CHEST {
			Total += 250
		}
	}

	Total += (5 - BaseMod.EnergyAD) * 25
	BaseMod.SetSource(Total)
}

func (p *Player) TriggerSeedOrder() *order.Order {
	OrderMod := p.PlayMod.getOrderMod()
	ChessMod := p.PlayMod.getChessMod()
	BaseMod := p.PlayMod.getBaseMod()
	if !BaseMod.GetSeed() {
		return nil
	}
	OrderMod.CreatOrderPool(BaseMod.Level, ChessMod.GetOrderEmit(), BaseMod.EnergyMul)
	ChampshipMod := p.PlayMod.getChampshipMod()
	NeedScore := champshipCfg.GetRewardTotalScore(ChampshipMod.Reward + 1)
	E := BaseMod.GetSource()
	ChessList := ChessMod.GetUnlockChessList()
	ChessBuff := ChessMod.GetChessBuf()
	AllChess := append(ChessList, ChessBuff...)
	NewOrder := &order.Order{}
	MaxQ := 0
	MinQ := 0
	// 计算Q值
	for _, Order := range OrderMod.OrderPool {
		Q := 0
		for _, v := range Order.MergeId {
			Color := mergeDataCfg.GetColorById(v)
			Lv := mergeDataCfg.GetLvById(v)
			Q1 := int(math.Pow(2, float64(Lv))) - 1
			Q2 := 0
			Q3 := 0
			for _, Chess := range AllChess {
				Lv1 := mergeDataCfg.GetLvById(Chess)
				Color1 := mergeDataCfg.GetColorById(Chess)
				Type := mergeDataCfg.GetTypeById(Chess)
				if Type != "Product" {
					continue
				}
				if Color != Color1 {
					continue
				}
				if Lv1 > Lv {
					continue
				}
				Q2 += int(math.Pow(2, float64(Lv1))) - 1
			}
			for _, Chess := range AllChess {
				if Chess == chess.CHESS_ZIXUAN_CHEST {
					if Lv < 3 {
						continue
					}
					Q3 += int(math.Pow(2, 3)) - 1
				}
				if Chess == chess.CHESS_HIGH_ZIXUAN_CHEST {
					if Lv < 7 {
						continue
					}
					Q3 += int(math.Pow(2, 7)) - 1
				}
				if Chess == chess.CHESS_SOURCE_CHEST {
					if Lv < 3 {
						continue
					}
					Q3 += int(math.Pow(2, 3)) - 1
					Q3 += int(math.Pow(2, 4)) - 1
				}
				if Chess == chess.CHESS_HIGH_SOURCE_CHEST {
					if Lv < 7 {
						continue
					}
					Q3 += int(math.Pow(2, 7)) - 1
					Q3 += int(math.Pow(2, 7)) - 1
				}
			}
			Q += max(Q1-Q2-Q3, 0)
		}
		Order.Q = Q
		MaxQ = max(MaxQ, Q)
		MinQ = min(MinQ, Q)
	}

	if E > MaxQ {
		return nil
	}
	// 生成订单
	var ProduceChessList []int
	for _, v := range AllChess {
		Type := mergeDataCfg.GetTypeById(v)
		if Type != "Product" {
			continue
		}
		ProduceChessList = append(ProduceChessList, v)
	}
	if E == MaxQ {
		for _, Order := range OrderMod.OrderPool {
			if Order.Q == MaxQ {
				NewOrder = Order
				break
			}
		}
		var EmitTypeList []string
		for _, v := range NewOrder.MergeId {
			Color := mergeDataCfg.GetColorById(v)
			EmitType := mergeDataCfg.GetEmitTypeByColor(Color)
			EmitTypeList = append(EmitTypeList, EmitType)
		}
		var ChessList []int
		for _, v := range ProduceChessList {
			Color := mergeDataCfg.GetColorById(v)
			EmitType := mergeDataCfg.GetEmitTypeByColor(Color)
			Lv := mergeDataCfg.GetLvById(v)
			if Lv < 3 || Lv > 4 {
				continue
			}
			if GoUtil.InStringArray(EmitType, EmitTypeList) {
				continue
			}
			ChessList = append(ChessList, v)
		}
		if len(ChessList) != 0 {
			RandChess := GoUtil.RandSlice(ChessList)
			Color := mergeDataCfg.GetColorById(RandChess)
			Lv := mergeDataCfg.GetLvById(RandChess)
			NewChess := mergeDataCfg.GetChessIdByLvAndColor(Lv, Color)
			NewOrder.MergeId = append(NewOrder.MergeId, NewChess)
		}
		return NewOrder
	}

	if E == MinQ {
		for _, Order := range OrderMod.OrderPool {
			if Order.Q == MinQ {
				return Order
			}
		}
	}

	if E < MinQ {
		for _, Order := range OrderMod.OrderPool {
			if Order.Q == MinQ {
				var ChessList []int
				for _, v := range ProduceChessList {
					Lv := mergeDataCfg.GetLvById(v)
					if Lv < 5 {
						ChessList = append(ChessList, v)
					}
				}
				if len(ChessList) != 0 {
					NewChess := GoUtil.RandSlice(ChessList)
					Order.MergeId = append(Order.MergeId, NewChess)
				}
				return Order
			}
		}
	}

	if E > MinQ && E < MaxQ {
		var L1 []*order.Order
		for _, Order := range OrderMod.OrderPool {
			if Order.Q > E {
				L1 = append(L1, Order)
			}
		}
		Smax := 0
		Smin := 0
		for _, Order := range L1 {
			Score := 0
			for _, v := range Order.MergeId {
				Lv := mergeDataCfg.GetLvById(v)
				Score += champshipCfg.GetChessScore(Lv)
			}
			Smax = max(Score, Smax)
			Smin = min(Score, Smin)
			Order.S = Score
		}

		if NeedScore > Smax {
			for _, Order := range OrderMod.OrderPool {
				if Order.Q == MinQ {
					var ChessList []int
					for _, v := range ProduceChessList {
						Lv := mergeDataCfg.GetLvById(v)
						if Lv < 5 {
							ChessList = append(ChessList, v)
						}
					}
					if len(ChessList) != 0 {
						NewChess := GoUtil.RandSlice(ChessList)
						Order.MergeId = append(Order.MergeId, NewChess)
					}
					return Order
				}
			}
		}
		if NeedScore == Smax {
			for _, Order := range L1 {
				if Order.S == Smax {
					return Order
				}
			}
		}

		if NeedScore == Smin {
			for _, Order := range L1 {
				if Order.S == Smin {
					return Order
				}
			}
		}
		var L2 []*order.Order
		for _, Order := range L1 {
			if Order.S > NeedScore {
				L2 = append(L2, Order)
			}
		}
		if len(L2) != 0 {
			sort.Slice(L2, func(i, j int) bool {
				return L2[i].Q < L2[j].Q
			})
			return L2[0]
		}
	}
	return NewOrder
}
