package charge

import (
	"fmt"
	"math"
	chargeCfg "server/conf/charge"
	mergeDataCfg "server/conf/merge_data"
	playroomCfg "server/conf/playroom"
	"server/game/mod/item"
	"server/game/mod/order"
	GoUtil "server/game_util"
	"server/msg"
	"server/pkg/github.com/name5566/leaf/log"
)

type ChargeMod struct {
	FirstCharge       int64            // 首次充值时间
	LastCharge        int64            // 最后一次充值时间
	EnergyShop        map[int]struct{} // 能量购买次数商店
	MaxCharge         float64          // 最大充值金额
	Charge            float64          // 总充值金额
	TodayCharge       float64          // 当日充值金额
	MonthCharge       float64          // 当月充值金额
	Total             int              // 总充值次数
	LastSpecialCharge int64            // 近35天最大充值的充值时间
	SpecialCharge     float64          // 近35天最大充值金额

	SpecialShop map[int]*SepcialShop // 特殊商店
	FreeShop    int                  // 已领取免费商店档次

	ChessShop map[int]*ChessShop // 棋子商店

	Gift map[int]int // 礼包

	Ad             bool // 是否购买免广告
	AdEndTime      int64
	PetWorkTime    int64 // 宠物打工时间
	LastWorkTime   int64 // 上次打工时间
	WishList       *WishList
	WeeklyDiscount map[int]int // 每周折扣购买次数
	WeeklyEndTime  int64
}

type WishList struct {
	Count    int
	ItemId   int
	SendList []int64
}
type Rand struct {
	ChessId int
	Diamond int
}
type ChessShop struct {
	Diamond int
	Count   int
	Id      int
}

type SepcialShop struct {
	Grade int
	Count int
}

var ChessDiamondCfg = map[int]int{
	1: 5,
	2: 10,
	3: 20,
	4: 50,
}

const (
	SPECIAL_TYPE_1 = 1 // 特惠礼包1
	SPECIAL_TYPE_2 = 2 // 特惠礼包2
)

const (
	PLAYROOM_SHOP = 1 // playroom商店
	CHESS_SHOP    = 2 // 棋子商店
	ENERGY_SHOP   = 3 // 能量商店
)
const (
	secondsIn35Days = 35 * 24 * 3600
	secondsIn7Days  = 7 * 24 * 3600
	secondsIn1Day   = 24 * 3600
)

func (c *ChargeMod) InitData() {
	if c.SpecialShop == nil {
		c.SpecialShop = make(map[int]*SepcialShop)
	}
	if c.EnergyShop == nil {
		c.EnergyShop = make(map[int]struct{})
	}
	if c.Gift == nil {
		c.Gift = make(map[int]int)
	}
	if c.WishList == nil {
		c.WishList = &WishList{
			Count:    0,
			ItemId:   0,
			SendList: make([]int64, 0),
		}
	}
	if c.WeeklyDiscount == nil {
		c.WeeklyDiscount = make(map[int]int)
	}
}

func (c *ChargeMod) GetMaxCharge() float64 {
	return c.MaxCharge
}

func (c *ChargeMod) Login(LogoutTime int64) {
	c.LastWorkTime = min(LogoutTime, c.PetWorkTime)
	c.PetWorkTime -= c.LastWorkTime
}

// resetSpecialChargeIfExpired 若距上次充値超过 35 天则清零特惠充値记录
func (c *ChargeMod) resetSpecialChargeIfExpired(now int64) {
	if c.LastCharge != 0 && now-c.LastCharge > secondsIn35Days {
		c.SpecialCharge = 0
	}
}

// 零点更新
func (c *ChargeMod) ZeroUpdate(Emit []int) {
	Now := GoUtil.Now()
	c.resetSpecialChargeIfExpired(Now)
	if GoUtil.IsFirstDayOfMonth() {
		c.MonthCharge = 0
	}
	c.FreeShop = 0
	SpecialGrade := 1
	c.TodayCharge = 0
	c.SpecialShop = make(map[int]*SepcialShop)
	SpecialShopCount := chargeCfg.GetSpecialShopCount()
	for i := 1; i <= 2; i++ {
		if c.Total == 0 {
			c.SpecialShop[i] = &SepcialShop{Grade: SpecialGrade, Count: 1}
			continue
		}
		m := c.SpecialCharge
		M := chargeCfg.GetSpecialShopGrade(m, i)
		a := min(2, GoUtil.FullWeeksSince(c.LastSpecialCharge))
		SpecialGrade = max(1, M-a)
		c.SpecialShop[i] = &SepcialShop{Grade: SpecialGrade, Count: SpecialShopCount}
	}
	if c.WishList != nil {
		c.WishList.SendList = nil
	}
	if c.IsWeeklyDiscountDay() && c.WeeklyEndTime < Now {
		c.WeeklyDiscount = make(map[int]int)
		c.WeeklyEndTime = GoUtil.ZeroTimestamp() + secondsIn7Days
	}
	c.InitChessShop(Emit)
}

// 十二点更新 重置商店
func (c *ChargeMod) NoonUpdate(Emit []int) {
	c.InitChessShop(Emit)
}

func (c *ChargeMod) FixBug(Emit []int) {
	if len(c.ChessShop) < 5 {
		c.InitChessShop(Emit)
	}
}

// 充值
func (c *ChargeMod) Fire(ChargeId int) (Item []*item.Item) {
	Money := chargeCfg.GetMoneyCharge(ChargeId)
	if Money == 0 {
		return
	}
	c.Charge += Money
	c.TodayCharge += Money
	c.MonthCharge += Money
	c.Total++
	Now := GoUtil.Now()
	if c.FirstCharge == 0 {
		c.FirstCharge = Now
	}
	c.resetSpecialChargeIfExpired(Now)
	c.LastCharge = Now
	if Money > c.MaxCharge {
		c.MaxCharge = Money
	}
	if Money > c.SpecialCharge {
		c.LastSpecialCharge = Now
		c.SpecialCharge = Money
	}
	Item = c.FireDiamondShop(ChargeId)
	if Item != nil {
		return
	}
	Item = c.FireEnergyShop(ChargeId)
	if Item != nil {
		return
	}
	Item = c.FireSpecialShop(ChargeId)
	if Item != nil {
		return
	}
	Item = c.FirePetCoinShop(ChargeId)
	if Item != nil {
		return
	}
	Item = c.FireGift(ChargeId)
	c.FireAd(ChargeId)
	return
}

// 钻石商店
func (c *ChargeMod) FireDiamondShop(ChargeId int) []*item.Item {
	return chargeCfg.GetDiamondShopReward(ChargeId)
}

// 宠物币商店
func (c *ChargeMod) FirePetCoinShop(ChargeId int) []*item.Item {
	return chargeCfg.GetPetCoinShopReward(ChargeId)
}

// 能量商店
func (c *ChargeMod) FireEnergyShop(ChargeId int) []*item.Item {
	id := chargeCfg.GetEnergyShopId(ChargeId)
	_, ok := c.EnergyShop[id]
	c.EnergyShop[id] = struct{}{}
	return chargeCfg.GetEnergyShopReward(ChargeId, ok)
}

// 特惠礼包
func (c *ChargeMod) FireSpecialShop(ChargeId int) []*item.Item {
	Type := chargeCfg.GetSpecialShopType(ChargeId)
	if _, ok := c.SpecialShop[Type]; !ok {
		return nil
	}
	if c.SpecialShop[Type].Count < 1 {
		log.Debug("special shop recharge max, type: %d, charge id: %d", Type, ChargeId)
		return nil
	}
	c.SpecialShop[Type].Count--
	return chargeCfg.GetSpecialShopReward(ChargeId)
}

// 通用礼包
func (c *ChargeMod) FireGift(ChargeId int) []*item.Item {
	Limit := chargeCfg.GetGiftLimit(ChargeId)
	if Limit == 0 {
		return nil
	}
	Id := chargeCfg.GetGiftId(ChargeId)

	if v, ok := c.Gift[Id]; ok {
		if v >= Limit {
			return nil
		}
	}
	c.Gift[Id]++
	return chargeCfg.GetGiftReward(ChargeId)
}

// 免广告礼包
func (c *ChargeMod) FireAd(ChargeId int) []*item.Item {
	AdChargeId := chargeCfg.GetAdChargeId()
	if ChargeId != AdChargeId {
		return nil
	}
	c.Ad = true
	return nil
}

// 免广告礼包
func (c *ChargeMod) FireAdReward(ChargeId int) []*item.Item {
	Items, PetWorkDay := chargeCfg.GetADReward(ChargeId)
	if PetWorkDay != 0 {
		Now := GoUtil.Now()
		if c.AdEndTime < Now {
			c.AdEndTime = Now + int64(PetWorkDay*secondsIn1Day)
		} else {
			c.AdEndTime += int64(PetWorkDay * secondsIn1Day)
		}
		c.PetWorkTime += int64(PetWorkDay * secondsIn1Day)
		c.Ad = true
	}
	return Items
}

// 免费商店
func (c *ChargeMod) FireFreeShop() ([]*item.Item, error) {
	if c.FreeShop >= 2 {
		return nil, fmt.Errorf(" free shop reward max")
	}
	c.FreeShop++
	return chargeCfg.GetFreeShopReward(c.FreeShop), nil
}

// 初始化棋子商店
func (c *ChargeMod) InitChessShop(Emit []int) {
	if len(Emit) == 0 {
		return
	}
	c.ChessShop = make(map[int]*ChessShop)
	//ColorList := make([]string, 0)
	RandList := make([]*Rand, 0)

	for _, v := range Emit {
		ProduceList := mergeDataCfg.GetEmitProduceType(v)
		for _, p := range ProduceList {
			ChessList := order.GetChessByDiff(v, 1, order.DIFF_MID, p)
			if len(ChessList) == 1 {
				ChessList = append(ChessList, ChessList[0]-1)
			}
			//ColorType := mergeDataCfg.GetColorType(p)
			for _, c := range ChessList {
				if c == 0 {
					continue
				}
				ChessLv := mergeDataCfg.GetLvById(c)
				DynamicLv := mergeDataCfg.GetAdjust(v, p, 0)
				ChessLv += DynamicLv
				Diamond := math.Round(math.Pow(2, float64(ChessLv-1)) / 5)
				Diamond = max(1, Diamond)
				RandList = append(RandList, &Rand{ChessId: c, Diamond: int(Diamond)})
			}
		}
	}
	randList := make([]interface{}, len(RandList))
	for k, v := range RandList {
		randList[k] = v
	}
	L := GoUtil.RandSliceNum2(randList, 5)
	for k, v := range L {
		Diamond := v.(*Rand).Diamond
		ChessId := v.(*Rand).ChessId
		if ChessId == 0 {
			continue
		}
		c.ChessShop[k+1] = &ChessShop{Diamond: Diamond, Count: 5, Id: ChessId}
	}
}

// 购买能量
func (c *ChargeMod) BuyEnergy(IsWeeklyDiscount bool) ([]*item.Item, []*item.Item, int) {
	diamond := 40
	if IsWeeklyDiscount {
		LimitNum := c.WeeklyDiscount[0]
		Discount, WeeklyLimit := chargeCfg.GetWeeklyInfo(0)
		if LimitNum < WeeklyLimit {
			diamond = int(math.Ceil(float64(diamond) * float64(Discount) / 100.0))
			c.WeeklyDiscount[0] = LimitNum + 1
		}
	}
	return []*item.Item{
			item.NewItem(item.ITEM_DIAMOND_ID, -diamond),
			item.NewItem(item.ITEM_ENERGY_ID, 100),
		}, []*item.Item{
			item.NewItem(item.ITEM_ENERGY_ID, 100),
		}, diamond
}

// 购买棋子
func (c *ChargeMod) BuyChess(Chess int, IsWeeklyDiscount bool) ([]*item.Item, []*item.Item, int, error) {
	v, ok := c.ChessShop[Chess]
	if !ok {
		return nil, nil, 0, fmt.Errorf("BuyChess chess id not exist id:%d", Chess)
	}

	if v.Count <= 0 {
		return nil, nil, 0, fmt.Errorf("BuyChess chess count less zero id:%d", Chess)
	}
	v.Count--
	diamond := v.Diamond
	if IsWeeklyDiscount {
		LimitNum := c.WeeklyDiscount[Chess]
		Discount, WeeklyLimit := chargeCfg.GetWeeklyInfo(Chess)
		if LimitNum < WeeklyLimit {
			diamond = int(math.Ceil(float64(diamond) * float64(Discount) / 100))
			if diamond == v.Diamond {
				diamond -= 1
			}
			diamond = max(1, diamond)
			c.WeeklyDiscount[Chess] = LimitNum + 1
		}
	}
	return []*item.Item{
			item.NewItem(item.ITEM_DIAMOND_ID, diamond),
		}, []*item.Item{
			item.NewItem(v.Id, 1),
		}, v.Id, nil
}

// 棋子商店解锁
func (c *ChargeMod) TriggerChargeUnlock(Lv int, Emit []int) {
	c.InitChessShop(Emit)
}

// 添加心愿单
func (c *ChargeMod) AddWish(Id, Type int) ([]*item.Item, error) {
	ItemId := 0
	switch Type {
	case PLAYROOM_SHOP:
		ItemId, _, _, _ = playroomCfg.GetShopItem(Id)
	}
	if ItemId == 0 {
		return nil, fmt.Errorf("AddWish itemid not exist id:%d", Id)
	}
	var Items []*item.Item
	if c.WishList.ItemId != 0 {
		if c.WishList.ItemId == ItemId {
			return nil, fmt.Errorf("AddWish itemid already exist id:%d", Id)
		}
		Items = append(Items, item.NewItem(item.ITEM_ENERGY_ID, c.WishList.Count))
		c.WishList.Count = 0
	}
	c.WishList.ItemId = ItemId
	return Items, nil
}

// 获取心愿单奖励
func (c *ChargeMod) GetWish() ([]*item.Item, error) {
	if c.WishList.ItemId == 0 {
		return nil, fmt.Errorf("AddWishCount itemid not exist")
	}
	Max := chargeCfg.GetWishCount(c.WishList.ItemId)
	if c.WishList.Count < Max {
		return nil, fmt.Errorf("AddWishCount count max")
	}
	rewardItemId := c.WishList.ItemId
	c.WishList.Count = 0
	c.WishList.ItemId = 0
	return []*item.Item{item.NewItem(rewardItemId, 1)}, nil
}

// 发送心愿单
func (c *ChargeMod) SendWishBeg(Uids []int64) error {
	for _, v := range Uids {
		if GoUtil.InArray64(v, c.WishList.SendList) {
			return fmt.Errorf("SendWishBeg uid already exist uid:%d", v)
		}
	}
	c.WishList.SendList = append(c.WishList.SendList, Uids...)
	return nil
}

// 增加心愿单完成度
func (c *ChargeMod) AddWishCount() {
	if c.WishList.ItemId == 0 {
		return
	}
	Max := chargeCfg.GetWishCount(c.WishList.ItemId)
	if c.WishList.Count >= Max {
		return
	}
	c.WishList.Count++
}

// 是否在每周折扣日
func (c *ChargeMod) IsWeeklyDiscountDay() bool {
	Day := chargeCfg.GetWeeklyDiscountDay()
	if Day == -1 {
		return false
	}
	Weekday, _ := GoUtil.GetWeekdayAndHour()
	return Weekday == Day || c.WeeklyEndTime > GoUtil.Now()
}

// 重置每周折扣
func (c *ChargeMod) ResetWeeklyDiscount() {
	if c.IsWeeklyDiscountDay() {
		return
	}
	c.WeeklyDiscount = make(map[int]int)
}

// 宠物打工数据
func (c *ChargeMod) PetWorkBackData() *msg.LogoutPetWork {
	res := &msg.LogoutPetWork{
		WorkTime:   c.LastWorkTime,
		RemainTime: c.PetWorkTime,
	}
	c.LastWorkTime = 0
	return res
}

func (c *ChargeMod) GetWeeklyEndTime() int64 {
	return c.WeeklyEndTime
}

func (c *ChargeMod) SetWeeklyEndTime(EndTime int64) {
	c.WeeklyEndTime = EndTime
}
