package info

import (
	element "blazing/common/data/Element"
	"blazing/common/data/xmlres"
	"blazing/modules/blazing/model"
	"math/rand"

	"context"
	"fmt"
	"strconv"

	"github.com/gogf/gf/v2/os/glog"
	"github.com/shopspring/decimal"
	"github.com/tnnmigga/enum"
)

const BattleSkillEntityCtx = "skill"

// EnumSkillType 技能类型枚举基础类型
type EnumCategory int

// SkillType 技能类型枚举实例（使用enum包创建）
// 与原Java枚举保持相同的数值映射：PHYSICAL=1, SPECIAL=2, STATUS=4
var Category = enum.New[struct {
	PHYSICAL EnumCategory `enum:"1"` // 物理攻击
	SPECIAL  EnumCategory `enum:"2"` // 特殊攻击
	STATUS   EnumCategory `enum:"4"` // 状态技能
	Fixed    EnumCategory // 固定伤害
	Percent  EnumCategory // 百分比伤害
	True     EnumCategory // 真伤
	ALL      EnumCategory //任何类型
}]()

// BattleSkillEntity 战斗技能实体
// 实现了战斗中技能的所有属性和行为，包括PP管理、技能使用、属性获取等
// 战斗中可以修改技能实体值,比如是否暴击,是否必中等
type BattleSkillEntity struct {
	xmlres.Move
	PP          int
	DamageZone  map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值
	DamageValue decimal.Decimal                                                // 伤害值
	Rand        *rand.Rand
	Pet         *BattlePetEntity
}

// CreateBattleSkillWithInfinity 创建战斗技能实例（可指定是否无限PP）
func CreateBattleSkillWithInfinity(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *BattleSkillEntity {
	//如果PP是-1 ,那就是无限PP
	// ID小于10001的视为无效技能

	if skill.ID < 10001 {
		return nil
	}

	var ret BattleSkillEntity
	ret.Rand = rand
	ret.Pet = pet
	// 从资源仓库获取技能数据
	move, ok := xmlres.SkillMap[int(skill.ID)]

	if !ok {
		glog.Error(context.Background(), "技能ID无效", "id", skill.ID)
	}
	ret.Move = move
	// // 解析副作用参数
	// sideEffectArgs := parseSideEffectArgs(move.SideEffectArg)
	// tt := strings.Split(move.SideEffect, " ")
	// rf, err := strSliceToIntSlice(tt)
	// if err == nil {
	// 	ret.SideEffects = rf
	// }
	ret.PP = int(skill.PP)
	// ret.SideEffectArgs = sideEffectArgs
	ret.DamageZone = make(map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第一层类型

	for _, v := range enum.Values[EnumCategory](Category) {
		ret.DamageZone[v] = make(map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第二层是否是加还是减
		for _, t := range enum.Values[EnumsZoneType](DamageC) {
			ret.DamageZone[v][t] = make(map[EnumsZoneType][]float64) //初始化第三层时乘还是加
			for _, s := range enum.Values[EnumsZoneType](DamageC) {
				ret.DamageZone[v][t][s] = make([]float64, 0) //初始化第四层 数组

			}
		}
	}

	return &ret
}

// 将字符串切片转换为整数切片
func strSliceToIntSlice(strs []string) ([]int, error) {
	intSlice := make([]int, 0, len(strs)) // 预分配容量，提高性能

	for _, s := range strs {
		// 将字符串转换为整数
		num, err := strconv.Atoi(s)
		if err != nil {
			// 转换失败时返回错误（包含具体的错误信息和失败的字符串）
			return nil, fmt.Errorf("无法将字符串 '%s' 转换为整数: %v", s, err)
		}
		intSlice = append(intSlice, num)
	}

	return intSlice, nil
}

// CanUse 检查技能是否可以使用（PP是否充足）
func (s *BattleSkillEntity) CanUse() bool {
	return s.PP > 0
}

// 获取技能类型
func (s *BattleSkillEntity) Category() EnumCategory {
	return EnumCategory(s.Move.Category)
}

// 获取技能属性
func (s *BattleSkillEntity) Type() *element.ElementCombination {
	ret, _ := element.NewElementCombination(s.Move.Type)
	return ret
}

// // 技能产生effect
// func (u *BattleSkillEntity) NewEffect(ctx context.Context)*node.EffectNode {

// 	ret := node.EffectNode{}
// 	ctx = context.WithValue(ctx, BattleSkillEntityCtx, &ret) //添加用户到上下文
// 	ret.ctx = ctx

// }
// 解析副作用参数字符串为整数列表

// 获取技能名称，为空时使用ID
func getSkillName(move *BattleSkillEntity) string {
	if move.Name == "" {
		return strconv.FormatInt(int64(move.ID), 10)
	}
	return move.Name
}

// 获取副作用列表，处理空值情况
// func getSideEffects(move *BattleSkillEntity) []int {
// 	if move.SideEffect == "" {
// 		return []int{}
// 	}
// 	return move.SideEffects
// }

type EnumsZoneType int

var DamageZone = enum.New[struct {
	add EnumsZoneType // 加区

	nul EnumsZoneType // 乘区
}]()
var DamageC = enum.New[struct {
	boost     EnumsZoneType //增伤区
	reduction EnumsZoneType // 减伤区
}]()

// func (s *BattleSkillEntity) Random() *random.RandomXS128 {
// 	battle, _ := s.ctx.Value(BattleContainerCtx).(*Battle1V1)

// 	return battle.Rand

// }

// 获得指定的+-区
func (s *BattleSkillEntity) GetAddValue(e EnumCategory, c EnumsZoneType) decimal.Decimal {

	t, ok := s.DamageZone[e][c][DamageZone.add]
	if ok {
		var ttt decimal.Decimal

		for _, v := range t {
			t1 := decimal.NewFromFloat(v)
			ttt.Add(t1)
		}
		return ttt
	}
	return decimal.NewFromFloat(0)
}

// 获得指定的*/区
func (s *BattleSkillEntity) GetMulValue(e EnumCategory, c EnumsZoneType) decimal.Decimal {

	t, ok := s.DamageZone[e][c][DamageZone.nul]
	if ok {
		var ttt decimal.Decimal

		for _, v := range t {
			t1 := decimal.NewFromFloat(v)
			ttt.Mul(t1)
		}
		return ttt
	}

	return decimal.NewFromFloat(0)

}

// 设置指定的值
// 三维map 伤害类型-》增还是减-》加还是乘-》值
func (s *BattleSkillEntity) PutDamageZone(e EnumCategory, dtype EnumsZoneType, value float64, ftype EnumsZoneType) {
	s.DamageZone[e][dtype][ftype] = append(s.DamageZone[e][dtype][ftype], value)
	// switch dtype { //判断伤害节点段

	// //case Zone.Power: //特判乘算区的乘运算

	// default:
	// 	switch ftype { //判断设置哪个算区

	// 	case true: // 乘算区
	// 		old := s.GetAddValue(e)

	// 		new := decimal.NewFromFloat(value)
	// 		s.DamageZone[dtype] = float64(old.Add(new).IntPart())

	// 	case false: //  加算区
	// 		old := s.GetMulValue(e)

	// 		new := decimal.NewFromFloat(value)
	// 		s.DamageZone[dtype] = float64(old.Add(new).IntPart())

	// 	}
	// }

}

// func (s *BattleSkillEntity) Pet() (*BattlePetEntity, bool) {
// 	pet, ok := s.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)

// 	return pet, ok

// }

// 暴击伤害 返回暴击率和是否暴击
func (s *BattleSkillEntity) IsCritical() (decimal.Decimal, bool) {

	return decimal.NewFromFloat(1), true

}

// 计算是否命中
func (s *BattleSkillEntity) AttackTime() uint32 {

	if int64(s.Pet.Accuracy(int64(s.Accuracy))) > s.Rand.Int63n(100) {
		return 1
	}
	return 0

}
func (s *BattleSkillEntity) CriticalsameTypeBonus() decimal.Decimal {

	// 6. 同系加成（属性相同则乘以同系加成倍率，否则1）
	sameTypeBonus := decimal.NewFromFloat(1.0)
	if s.Type() == s.Pet.Type() { //使用本系
		sameTypeBonus = decimal.NewFromFloat(1.5)
	}

	stype := s.Type()
	ptype := s.Pet.Type()

	if stype.Secondary == nil && ptype.Secondary != nil && (stype.Primary == ptype.Primary || stype.Primary == *ptype.Secondary) { //判断技能属性是否是精灵双属性之一
		sameTypeBonus = decimal.NewFromFloat(1.5)
	}
	return sameTypeBonus
}

func (s *BattleSkillEntity) criticalrandom() decimal.Decimal {

	randomnum := s.Rand.Int31n(39) + 217
	// 10. 随机倍率，随机值除以255
	randomFactor := decimal.NewFromInt(int64(randomnum)).Div(decimal.NewFromInt(255))
	return randomFactor

}

// 计算技能威力
func (s *BattleSkillEntity) CalculatePower(deftype int) uint32 {

	// 1. 计算等级因子 (level * 0.4 + 2)
	levelFactor := decimal.NewFromInt(int64(s.Pet.Info.Level)).
		Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2))

	// 2. 计算威力因子 (基础威力 + 加算) * 乘算

	//powerAdd := decimal.NewFromFloat(s.GetAddValue(EnumCategory., true)) //威力加算区
	powerAdd_all := s.GetAddValue(Category.ALL, DamageC.boost)
	powerMul_all := s.GetMulValue(Category.ALL, DamageC.boost)

	var (
		powerAdd_p decimal.Decimal //威力加算
		powerMul_p decimal.Decimal //威力乘算
		attackDec  decimal.Decimal //攻击值
		defenseDec decimal.Decimal //防御值
		//damageReduction decimal.Decimal //伤害百分比减免
	)
	switch s.Category() { //判断技能类型
	case Category.PHYSICAL:

		powerAdd_p = powerAdd_all.Add(s.GetAddValue(Category.PHYSICAL, DamageC.boost))
		powerMul_p = powerMul_all.Add(s.GetMulValue(Category.PHYSICAL, DamageC.boost))
		attackDec = decimal.NewFromInt(int64(s.Pet.Attack()))
		defenseDec = decimal.NewFromInt(int64(s.Pet.Defense()))
		//damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.ATK_RESISTANCE])

	case Category.SPECIAL:
		powerAdd_p = powerAdd_all.Add(s.GetAddValue(Category.SPECIAL, DamageC.boost))
		powerMul_p = powerMul_all.Add(s.GetMulValue(Category.SPECIAL, DamageC.boost))
		attackDec = decimal.NewFromInt(int64(s.Pet.SAttack()))
		defenseDec = decimal.NewFromInt(int64(s.Pet.SDefense()))
		//damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.SP_ATK_RESISTANCE])

	default:
		return 0
	}

	if powerMul_p.IntPart() == 0 {
		powerMul_p = decimal.NewFromInt(1)
	}
	powerZone := decimal.NewFromInt(int64(s.Power)).Add(powerAdd_p).Mul(powerMul_p)
	// 5. 基础伤害公式：等级因子 * 威力因子 * 攻击 / 防御 / 50 + 2
	baseDamage := levelFactor.
		Mul(powerZone).
		Mul(attackDec).
		Div(defenseDec).
		Div(decimal.NewFromInt(50)).
		Add(decimal.NewFromInt(2))

	t, _ := element.NewElementCalculator().GetOffensiveMultiplier(s.Type().ID, deftype)

	typeRate := decimal.NewFromFloat(t)

	damage := baseDamage.
		Mul(s.CriticalsameTypeBonus()). // 同属性加成
		Mul(typeRate).                  // 克制系数

		Mul(s.criticalrandom()) //随机波动
	v, ok := s.IsCritical() //获取暴击
	if ok {
		damage.Mul(v)
	}
	return uint32(damage.IntPart())

}
