package model

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

	"time"

	"github.com/gogf/gf/v2/util/gconv"
)

// 除数数组（放大100倍）
// 数组按递增顺序排列，用于判断个体值等级
var divisors = []int{
	600, 1200, 1900, 2700, 3600, 4600, 5700, 6900, 8200, 9600,
	11100, 12700, 14400, 16200, 18100, 20100, 22100, 24000,
	25800, 27500, 29100, 30600, 32000, 33300, 34500, 35600,
	36600, 37500, 38300, 39000, 39600,
}

// CalculateIndividual 根据给定的a值计算个体值
// 返回值表示a大于等于多少个除数（范围：0-31）
func CalculateIndividual(a int) int {
	individual := 0
	for _, divisor := range divisors {
		if a >= divisor {
			individual++
		} else {
			break // 数组是递增的，可提前跳出循环
		}
	}
	return individual
}

// CalculateIndividualValue 计算个体值（0-31）
// 接收外部随机数生成器，便于控制随机性和复用
func CalculateIndividualValue(random *rand.Rand) int {
	// 生成0-40000的随机数，作为个体值计算的输入
	a := random.Intn(40001)
	return CalculateIndividual(a)
}

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"`
}
type PetEX struct {
	Pet
	Data PetInfo `orm:"data" json:"data"`
	
}

type PetS struct {
	Pet
	Data []PetInfo `orm:"data" dc:"资源规格"`
}

func LastFourElements[T any](s []T) []T {
	n := len(s)
	if n <= 4 {
		// 切片长度小于等于4时，返回整个切片
		return s
	}
	// 切片长度大于4时，返回最后4个元素（从n-4索引到末尾）
	return s[n-4:]
}

// -1是随机
// * @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 {
	// 设置随机数种子，确保每次运行生成不同的随机数序列
	rand.Seed(time.Now().UnixNano())

	p := &PetInfo{ID: uint32(id),

		EffectInfo: make([]PetEffectInfo, 0),
		CatchTime:  uint32(time.Now().Unix()),
		Level:      uint32(level)} //等级

	if shinyid != -1 {
		p.Shiny = uint32(shinyid)
	} else {

	}
	if natureId != -1 {
		p.Nature = uint32(natureId)
	} else {
		p.Nature = uint32(rand.Intn(25))
	}
	if dv != -1 {
		p.Dv = uint32(dv)
	} else {
		p.Dv = uint32(CalculateIndividualValue(rand.New(rand.NewSource(time.Now().UnixNano()))))
	}

	if abilityTypeEnum != -1 {
		if abilityTypeEnum != 0 {
			v := xmlres.PlayerEffectMAP[int(abilityTypeEnum)]
			p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
				Idx:    uint16(gconv.Int16(v.Idx)),
				Status: 1,
				EID:    uint16(gconv.Int16(v.Eid)),
				Args:   v.ArgsS,
			})
		}

	} else {
		for i, v := range xmlres.PlayerEffectMAP {
			if rand.Intn(len(xmlres.PlayerEffectMAP)) == i {
				p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
					Idx:    uint16(gconv.Int16(v.Idx)),
					Status: 1,
					EID:    uint16(gconv.Int16(v.Eid)),
					Args:   v.ArgsS,
				})
			}

		}

	}

	tttt := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) //获取最后四个技能,如果不足,那就取全部技能
	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))
	p.CalculatePetPane()
	p.Hp = p.MaxHp

	return p
}

// 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:"最大生命" `
	// * battle_lv: atk(0), def(1), sp_atk(2), sp_def(3), spd(4), accuracy(5)
	Prop [5]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 精灵特性信息结构
// <!-- NewSeIdx: 精灵特效索引 (默认0: 无效) -->
// <!-- Type: 0 - 仅单人战斗; 1 - 仅组队战斗; 2 - both; (默认0: 仅单人) -->
// <!-- Eid: 精灵特效eid (默认0: 无效) -->
// <!-- Stat: 精灵特效Stat: 0: 无效(默认值), 1: 永久, 2: 有`有效次数'的特效 3: 爆发特效 4: 异能精灵特质-->
// <!-- Times: 精灵特效可使用次数: 当type==2时有效 (默认值:0) -->
// <!-- Args: 特效参数, 不超过8个 (注意: 每个参数不能超过 65535) -->
// <!-- AdditionType:特效加成类型 1 种族值加成 2 技能威力加成 -->
type PetEffectInfo struct {
	ItemID    uint32 `struc:"uint32" json:"item_id"` //如果是能量珠,就显示
	Idx       uint16 `struc:"skip" json:"new_se_idx"`
	Status    byte   `struc:"byte" json:"status"`      //特性为1,能量珠为2
	LeftCount byte   `struc:"byte" json:"left_count"`  //剩余次数
	EID       uint16 `struc:"uint16" json:"effect_id"` //特效ID
	ArgsLen   uint32 `struc:"sizeof=Args"`

	Args []int ` json:"Args"` //自定义参数装载

}

// 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)
}
