package controller

import (
	"errors"
	"fmt"
	"ktogame/models"
	"strings"

	"github.com/go-xorm/xorm"
)

func UpdateSuperiorsPerformance(engine *xorm.Engine, superiorsStr string, amount float64) error {
	ids := strings.Split(superiorsStr, ",")
	if len(ids) <= 0 {
		return nil
	}
	var supers []models.UserInfo
	for _, sid := range ids {
		var tmpUser models.UserInfo
		ok, err := engine.Where("id = ?", sid).Get(&tmpUser)
		if err != nil {
			return err
		}
		if !ok {
			continue
		}
		supers = append(supers, tmpUser)
	}
	if len(supers) == 0 {
		return nil
	}

	var rp models.RewardsPool
	_, err := engine.Id(1).Get(&rp)
	if err != nil {
		return err
	}

	for _, super := range supers {
		var per models.Performance
		ok, err := engine.Id(super.Addr).Get(&per)
		if err != nil {
			fmt.Println(err)
			continue
		}
		if !ok {
			continue
		}

		per.TotalPerformance += amount
		if per.TotalPerformance >= CommunityMarkit*Decimals {
			if per.Recorded == 0 {
				var super models.Performance
				ok, err := engine.Id(per.Addr).Get(&super)
				if err != nil {
					fmt.Println(err)
					continue
				}
				if !ok {
					continue
				}
				super.MarketNum += 1
				_, err = engine.ID(super.Addr).Cols("markit_num").Update(&super)
				if err != nil {
					fmt.Println(err)
					continue
				}
				per.Recorded = 1
			}
		}

		var level int = 0
		for i := 1; i < len(PerformanceLevel); i++ {
			if PerformanceLevel[i-1] <= per.TotalPerformance && per.TotalPerformance < PerformanceLevel[i] {
				level = i
				break
			}
		}
		if level > 0 {
			if level > per.PerformanceLevel {
				ratio := PerformanceRatio[level] - PerformanceRatio[per.PerformanceLevel]
				rewards := amount * ratio
				if rp.TeamPerformance >= rewards {
					rp.TeamPerformance -= rewards     //pool sub rewards
					per.PerformanceRewards += rewards //user add rewards to PerformanceRewards
					per.PerformanceLevel = level
					//update available
					err := UpdateAvailableRewards(engine, rewards, super.Addr, false, false)
					if err != nil {
						return err
					}
					_, err = engine.ID(super.Addr).Cols("total_performance,performance_rewards,performance_level").Update(&per)
					if err != nil {
						return err
					}
				}
			}
		}
	}

	_, err = engine.ID(1).Cols("team_performance").Update(&rp)
	if err != nil {
		return err
	}

	return nil
}

func UpdateRewardsPool(engine *xorm.Engine, amount float64) error {
	var rp models.RewardsPool
	rp.TeamPerformance = amount * 0.15
	rp.TeamCultivate = amount * 0.10
	rp.TotalPool += amount
	_, err := engine.ID(1).Update(&rp)
	if err != nil {
		return err
	}
	return nil
}

func UpdateAvailableRewards(engine *xorm.Engine, rewards float64, uaddr string, join, isdirect bool) error {
	a_rewards := rewards * 60 / 100
	a_reinput := rewards * 40 / 100
	var user models.UserInfo
	ok, err := engine.Id(uaddr).Get(&user)
	if err != nil {
		return err
	}
	if !ok {
		return nil
	}
	user.AvailableClaim = a_rewards
	user.AvailableReinput = a_reinput
	if join {
		if isdirect {
			user.DirectNumber += 1
			user.DirectRewards += rewards
			_, err = engine.ID(user.Addr).Cols("available_claim,available_reinput,direct_number,direct_rewards").Update(&user)
			if err != nil {
				return err
			}

		} else {
			user.IndirectNumber += 1
			user.IndirectRewards += rewards
			_, err = engine.ID(user.Addr).Cols("available_claim,available_reinput,indirect_number,indirect_rewards").Update(&user)
			if err != nil {
				return err
			}
		}
	} else {
		_, err = engine.ID(user.Addr).Cols("available_claim,available_reinput").Update(&user)
		if err != nil {
			return err
		}
	}
	return nil
}

func UpdateCommunityGift(engine *xorm.Engine, amount float64, uaddr string) error {
	var user, tmpUser models.UserInfo
	ok, err := engine.Id(uaddr).Get(&user)
	if err != nil {
		return err
	}
	if !ok {
		return nil
	}

	ok, err = engine.Desc("id").Get(&tmpUser)
	if err != nil {
		return err
	}
	if !ok {
		return errors.New("engine get info failed")
	}

	var leftNum, rightNum int64
	if user.Id >= 26 {
		leftNum = 25
	} else {
		leftNum = user.Id - 1
	}
	if tmpUser.Id-user.Id >= 25 {
		rightNum = 25
	} else {
		rightNum = tmpUser.Id - user.Id
	}

	rewards := amount * (float64(leftNum+rightNum) / 100)
	err = UpdateAvailableRewards(engine, rewards, user.Addr, false, false)
	if err != nil {
		return err
	}

	var per models.Performance
	ok, err = engine.Id(uaddr).Get(&per)
	if err != nil {
		return err
	}
	if !ok {
		return nil
	}
	per.CommunityGift += rewards
	_, err = engine.ID(uaddr).Cols("community_gift").Update(&per)
	if err != nil {
		return err
	}

	return nil
}

func UpdateCommunityNodes(engine *xorm.Engine, amount float64) error {
	var nodes []models.UserInfo
	err := engine.Where("state = ?", CommunityUsers).Find(&nodes)
	if err != nil {
		return err
	}
	if len(nodes) == 0 {
		return nil
	}
	rewards := (amount * 5 / 100) / float64(len(nodes))
	for _, node := range nodes {
		err = UpdateAvailableRewards(engine, rewards, node.Addr, false, false)
		if err != nil {
			fmt.Println(err)
			continue
		}
	}
	return nil
}

func UpdateMarket(engine *xorm.Engine, amount float64) error {
	var pers []models.Performance
	err := engine.Where("market_num >= ?", 2).Find(&pers)
	if err != nil {
		return err
	}
	var rp models.RewardsPool
	ok, err := engine.Id(1).Get(&rp)
	if err != nil {
		return err
	}
	if !ok {
		return nil
	}

	for _, per := range pers {
		var level int = 0
		for i := 1; i < len(MarketLevel); i++ {
			if MarketLevel[i-1] <= per.MarketNum && per.MarketNum < MarketLevel[i] {
				level = i
				break
			}
		}
		if level > 0 {
			if level > per.MarketLevel {
				ratio := MarketRatio[level] - MarketRatio[per.MarketLevel]
				rewards := amount * ratio
				if rp.TeamCultivate >= rewards {
					rp.TeamCultivate -= rewards  //pool sub rewards
					per.MarketRewards += rewards //user add rewards to PerformanceRewards
					per.MarketLevel = level
					//update available
					err := UpdateAvailableRewards(engine, rewards, per.Addr, false, false)
					if err != nil {
						return err
					}
					_, err = engine.ID(per.Addr).Cols("market_level,market_rewards").Update(&per)
					if err != nil {
						return err
					}
				}
			}
		}
	}
	_, err = engine.ID(1).Cols("team_performance").Update(&rp)
	if err != nil {
		return err
	}
	return nil
}
