package model

import (
	"blazing/common/data/xmlres"
	"blazing/cool"
	"math"
	"math/rand"

	"time"
)

const TableNamePet = "pet"

// Pet mapped from table <pet>
type Pet struct {
	*cool.Model
	PlayerID  uint32 `gorm:"not null;index:idx_pet_by_player_id;comment:'所属玩家ID'" json:"player_id"`
	InBag     int    `gorm:"not null;comment:'是否在背包中'" json:"in_bag"` //"0为放入仓库，1为放入背包
	CatchTime uint32 `gorm:"not null;comment:'捕捉时间'" json:"catch_time"`
	// Owner     uint32 `struc:"skip"` //仅作为存储
	// FreedTime uint32 `struc:"skip"` //放生时间
	//是否可交易，这里应该定义在精灵ID里
	//是否上架
	Data string `gorm:"type:text;not null;comment:'精灵全部数据'" json:"data"`
}

func GetGaussRandomNum(min, max int64) int64 {
	σ := (float64(min) + float64(max)) / 2
	μ := (float64(max) - σ) / 3
	rand.Seed(time.Now().UnixNano())
	x := rand.Float64()
	x1 := rand.Float64()
	a := math.Cos(2*math.Pi*x) * math.Sqrt((-2)*math.Log(x1))
	result := a*μ + σ
	return int64(result)
}

// RandomInRange 从切片表示的范围中返回对应结果：
// - 切片包含1个元素时，返回该元素本身
// - 切片包含2个元素时，从[min, max]闭区间随机生成一个整数（自动调整min和max顺序）
// - 其他情况返回0
func RandomInRange(rangeSlice []int) int {
	rand.Seed(time.Now().UnixNano())
	switch len(rangeSlice) {
	case 1:
		// 只有一个元素时返回自身
		return rangeSlice[0]
	case 2:
		// 两个元素时处理为范围
		min, max := rangeSlice[0], rangeSlice[1]
		// 确保 min ≤ max
		if min > max {
			min, max = max, min
		}
		// 生成 [min, max] 区间的随机整数

		return int(GetGaussRandomNum(int64(min), int64(max))) //(rand.Intn(int(max-min+1)) + int(min))
	default:
		// 其他长度返回0
		return 0
	}
}
func LastFourElements[T any](s []T) []T {
	n := len(s)
	if n <= 4 {
		// 切片长度小于等于4时，返回整个切片
		return s
	}
	// 切片长度大于4时，返回最后4个元素（从n-4索引到末尾）
	return s[n-4:]
}

// * @param petTypeId 精灵类型ID
// * @param individualValue 个体值
// * @param natureId 性格ID
// * @param abilityTypeEnum 特性类型
// * @param isShiny 是否为闪光
// * @param level 等级
// * @return 生成的精灵实体
func GenPetInfo(id int, dv, natureId, abilityTypeEnum, shinyid, level []int) *PetInfo {

	p := &PetInfo{ID: uint32(id),
		Shiny:      uint32(RandomInRange(shinyid)),  //闪光
		Nature:     uint32(RandomInRange(natureId)), //性格
		Dv:         uint32(RandomInRange(dv)),
		EffectInfo: make([]PetEffectInfo, 0),
		CatchTime:  uint32(time.Now().Unix()),
		Level:      uint32(RandomInRange(level))} //等级

	p.EffectInfo = append(p.EffectInfo, PetEffectInfo{ItemID: uint32(RandomInRange(abilityTypeEnum))})
	naxml := xmlres.NatureRootMap[int(p.Nature)]
	petxml := xmlres.PetMAP[int(id)]
	tttt := make([]uint32, 0)
	for _, v := range petxml.LearnableMoves.Moves {
		if p.Level >= uint32(v.LearningLv) {
			tttt = append(tttt, uint32(v.ID))

		}

	}
	tttt = LastFourElements(tttt) //获取最后四个技能,如果不足,那就取全部技能
	for i := 0; i < len(tttt); i++ {
		p.SkillList[i].ID = tttt[i]
		p.SkillList[i].PP = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)

	}
	p.SkillListLen = uint32(len(tttt))
	// 计算各项属性
	hp := p.CalculatePetHPPanelSize(
		uint32(petxml.HP),
		p.Dv,
		p.Level,
		p.EvHp,
	)

	attack := p.CalculatePetPanelSize(
		uint32(petxml.Atk),
		p.Dv,
		p.Level,
		p.EvAttack,
		naxml.AttackCorrect,
	)

	defense := p.CalculatePetPanelSize(
		uint32(petxml.Def),
		p.Dv,
		p.Level,
		p.EvDefence,
		naxml.DefenseCorrect,
	)

	specialAttack := p.CalculatePetPanelSize(
		uint32(petxml.SpAtk),
		p.Dv,
		p.Level,
		p.EvSpecialAttack,
		naxml.SaCorrect,
	)

	specialDefense := p.CalculatePetPanelSize(
		uint32(petxml.SpDef),
		p.Dv,
		p.Level,
		p.EvSpecialDefense,
		naxml.SdCorrect,
	)

	speed := p.CalculatePetPanelSize(
		uint32(petxml.Spd),
		p.Dv,
		p.Level,
		p.EvSpeed,
		naxml.SpeedCorrect,
	)

	// 设置计算结果
	p.MaxHp = hp
	p.Hp = hp
	p.Attack = attack
	p.Defence = defense
	p.SpecialAttack = specialAttack
	p.SpecialDefence = specialDefense
	p.Speed = speed
	return p
}

// 计算HP面板值（无性格修正）
func (c *PetInfo) CalculatePetHPPanelSize(base, dv, level, ev uint32) uint32 {

	return uint32((float64(base)*2+float64(ev)/4.0+float64(dv))*(float64(level)/100.0) + float64(level) + 10)
}

// 计算其他属性面板值（带性格修正）
func (c *PetInfo) CalculatePetPanelSize(base, dv, level, ev uint32, natureCorrect float64) uint32 {

	base1 := float64((float64(base)*2+float64(ev)/4.0+float64(dv))*(float64(level)/100.0) + 5)
	return uint32(float64(base1) * natureCorrect)
}

// PetInfo 精灵信息结构（合并后的优化版本）
type PetInfo struct {

	// 精灵编号（@UInt long → uint32）
	ID uint32 `fieldDesc:"精灵编号" `

	// 名字：默认为全0，补齐到16字节（固定长度 → [16]byte）
	Name string `struc:"[16]byte" `

	// 个体值（@UInt long → uint32）
	Dv uint32 `fieldDesc:"个体值" `

	// 性格（@UInt long → uint32）
	Nature uint32 `fieldDesc:"性格" `

	// 等级（@UInt long → uint32）
	Level uint32 `fieldDesc:"等级" `

	// 当前等级已获得经验（@UInt long → uint32）
	Exp uint32 `fieldDesc:"当前等级已经获得的经验 2538" `

	// 当前等级所需经验（@UInt long → uint32）
	LvExp uint32 `fieldDesc:"当前等级所需的经验" `

	// 升到下一级的经验（@UInt long → uint32）
	NextLvExp uint32 `fieldDesc:"升到下一级的经验" `

	// 当前生命（@UInt long → uint32）
	Hp uint32 `fieldDesc:"当前生命" `

	// 最大生命（@UInt long → uint32）
	MaxHp uint32 `fieldDesc:"最大生命" `

	// 攻击（@UInt long → uint32）
	Attack uint32 `fieldDesc:"攻击" `

	// 防御（@UInt long → uint32）
	Defence uint32 `fieldDesc:"防御" `

	// 特攻（@UInt long → uint32）
	SpecialAttack uint32 `fieldDesc:"特攻" `

	// 特防（@UInt long → uint32）
	SpecialDefence uint32 `fieldDesc:"特防" `

	// 速度（@UInt long → uint32）
	Speed uint32 `fieldDesc:"速度" `

	// 生命学习力（@UInt long → uint32）
	EvHp uint32 `fieldDesc:"生命学习力" `

	// 攻击学习力（@UInt long → uint32）
	EvAttack uint32 `fieldDesc:"攻击学习力" `

	// 防御学习力（@UInt long → uint32）
	EvDefence uint32 `fieldDesc:"防御学习力" `

	// 特攻学习力（@UInt long → uint32）
	EvSpecialAttack uint32 `fieldDesc:"特攻学习力" `

	// 特防学习力（@UInt long → uint32，注意原Java拼写：evSpecialDefense）
	EvSpecialDefense uint32 `fieldDesc:"特防学习力" `

	// 速度学习力（@UInt long → uint32）
	EvSpeed      uint32 `fieldDesc:"速度学习力" `
	SkillListLen uint32
	// 技能信息：固定4条，空则赋值0（固定长度List → [4]SkillInfo，零值即符合“赋值0”）
	SkillList [4]SkillInfo

	// 捕捉时间（@UInt long → 若为时间戳用uint32；若需时间类型可改为time.Time，需配合序列化处理）
	CatchTime uint32 `fieldDesc:"捕捉时间" `

	// 捕捉地图（@UInt long → uint32）
	CatchMap uint32 `fieldDesc:"捕捉地图" `

	// 未知默认0（@UInt long → uint32）
	CatchRect uint32 `fieldDesc:"未知默认为0" `

	// 捕获等级默认0（@UInt long → uint32）
	CatchLevel    uint32 `fieldDesc:"捕获等级 默认为0" `
	EffectInfoLen uint16 `struc:"sizeof=EffectInfo"`
	// 特性列表：长度用UShort存储（变长List → []PetEffectInfo + 长度前缀规则）
	EffectInfo []PetEffectInfo `fieldDesc:"特性列表, 长度在头部以UShort存储" serialize:"lengthFirst,lengthType=uint16,type=structArray"`

	// 皮肤ID默认0（@UInt long → uint32）
	SkinID uint32 `fieldDesc:"皮肤id默认为0" `

	// 是否闪光（@UInt long → uint32，0=否，1=是）
	Shiny uint32 `fieldDesc:"是不是闪" `
	//	AbilityType uint32 `struc:"skip"` //特性
}

// PetEffectInfo 精灵特性信息结构
type PetEffectInfo struct {
	ItemID    uint32   `struc:"uint32" json:"item_id"`
	Status    byte     `struc:"byte" json:"status"`
	LeftCount byte     `struc:"byte" json:"left_count"`
	EffectID  uint16   `struc:"uint16" json:"effect_id"`
	Reserve1  byte     `struc:"byte" json:"reserve1"`
	Reserve2  byte     `struc:"byte" json:"reserve2"`
	Reserve3  byte     `struc:"byte" json:"reserve3"`
	Reserve4  [13]byte `struc:"[13]byte" json:"reserve4"`
}

// SkillInfo 精灵技能信息结构（SkillInfo）
type SkillInfo struct {
	ID uint32
	PP uint32
}

// TableName Pet's table name
func (*Pet) TableName() string {
	return TableNamePet
}

// GroupName Pet's table group
func (*Pet) GroupName() string {
	return "default"
}

// NewPet create a new Pet
func NewPet() *Pet {
	return &Pet{
		Model: cool.NewModel(),
	}
}

// init 创建表
func init() {
	_ = cool.CreateTable(&Pet{})
	//	fmt.Println(err)
}
