package element

import (
	"fmt"
	"math"
	"sync"
	"testing"
)

// 元素类型枚举（1-17单属性，完整覆盖）
type ElementType int

const (
	ElementTypeGrass     ElementType = 1  // 草
	ElementTypeWater     ElementType = 2  // 水
	ElementTypeFire      ElementType = 3  // 火
	ElementTypeFlying    ElementType = 4  // 飞行
	ElementTypeElectric  ElementType = 5  // 电
	ElementTypeSteel     ElementType = 6  // 机械
	ElementTypeGround    ElementType = 7  // 地面
	ElementTypeNormal    ElementType = 8  // 普通
	ElementTypeIce       ElementType = 9  // 冰
	ElementTypePsychic   ElementType = 10 // 超能
	ElementTypeFighting  ElementType = 11 // 战斗
	ElementTypeLight     ElementType = 12 // 光
	ElementTypeDark      ElementType = 13 // 暗影
	ElementTypeMythic    ElementType = 14 // 神秘
	ElementTypeDragon    ElementType = 15 // 龙
	ElementTypeSaint     ElementType = 16 // 圣灵
	ElementTypeDimension ElementType = 17 // 次元
)

// 元素名称映射（全属性对应）
var elementNameMap = map[ElementType]string{
	ElementTypeGrass:     "GRASS",
	ElementTypeWater:     "WATER",
	ElementTypeFire:      "FIRE",
	ElementTypeFlying:    "FLYING",
	ElementTypeElectric:  "ELECTRIC",
	ElementTypeSteel:     "STEEL",
	ElementTypeGround:    "GROUND",
	ElementTypeNormal:    "NORMAL",
	ElementTypeIce:       "ICE",
	ElementTypePsychic:   "PSYCHIC",
	ElementTypeFighting:  "FIGHTING",
	ElementTypeLight:     "LIGHT",
	ElementTypeDark:      "DARK",
	ElementTypeMythic:    "MYTHIC",
	ElementTypeDragon:    "DRAGON",
	ElementTypeSaint:     "SAINT",
	ElementTypeDimension: "DIMENSION",
}

// 双属性映射（完整配置，无遗漏）
var dualElementMap = map[int][2]int{
	21: {1, 10},  // 草 超能
	22: {1, 11},  // 草 战斗
	23: {1, 13},  // 草 暗影
	24: {2, 10},  // 水 超能
	25: {2, 13},  // 水 暗影
	26: {2, 15},  // 水 龙
	27: {3, 4},   // 火 飞行
	28: {3, 15},  // 火 龙
	29: {3, 10},  // 火 超能
	30: {4, 10},  // 飞行 超能
	31: {12, 4},  // 光 飞行
	32: {4, 15},  // 飞行 龙
	33: {5, 3},   // 电 火
	34: {5, 9},   // 电 冰
	35: {5, 11},  // 电 战斗
	36: {13, 5},  // 暗影 电
	37: {6, 7},   // 机械 地面
	38: {6, 10},  // 机械 超能
	39: {6, 15},  // 机械 龙
	40: {7, 15},  // 地面 龙
	41: {11, 7},  // 战斗 地面
	42: {7, 13},  // 地面 暗影
	43: {9, 15},  // 冰 龙
	44: {9, 12},  // 冰 光
	45: {9, 13},  // 冰 暗影
	46: {10, 9},  // 超能 冰
	47: {11, 3},  // 战斗 火
	48: {11, 13}, // 战斗 暗影
	49: {12, 14}, // 光 神秘
	50: {13, 14}, // 暗影 神秘
	51: {14, 10}, // 神秘 超能
	52: {16, 12}, // 圣灵 光
	53: {4, 14},  // 飞行 神秘
	54: {7, 10},  // 地面 超能
	55: {13, 15}, // 暗影 龙
	56: {16, 13}, // 圣灵 暗影
	66: {2, 11},  // 水 战斗
	69: {12, 13}, // 光 暗影
}

// 元素组合结构体
type ElementCombination struct {
	Primary   ElementType  // 主属性（1-17）
	Secondary *ElementType // 副属性（1-17，双属性时非空）
	ID        int          // 组合ID
}

// 创建元素组合（严格验证范围）
func NewElementCombination(id int) (*ElementCombination, error) {
	if atts, isDual := dualElementMap[id]; isDual {
		primaryID, secondaryID := atts[0], atts[1]
		if primaryID < 1 || primaryID > 17 {
			return nil, fmt.Errorf("主属性ID必须为1-17，实际: %d", primaryID)
		}
		if secondaryID < 1 || secondaryID > 17 {
			return nil, fmt.Errorf("副属性ID必须为1-17，实际: %d", secondaryID)
		}
		primary := ElementType(primaryID)
		secondary := ElementType(secondaryID)
		if primary > secondary {
			primary, secondary = secondary, primary
		}
		return &ElementCombination{
			Primary:   primary,
			Secondary: &secondary,
			ID:        id,
		}, nil
	}

	if id < 1 || id > 17 {
		return nil, fmt.Errorf("单属性ID必须为1-17，实际: %d", id)
	}
	return &ElementCombination{
		Primary:   ElementType(id),
		Secondary: nil,
		ID:        id,
	}, nil
}

// 判断是否为双属性
func (ec *ElementCombination) IsDual() bool {
	return ec.Secondary != nil
}

// 获取所有属性
func (ec *ElementCombination) Elements() []ElementType {
	if ec.IsDual() {
		return []ElementType{ec.Primary, *ec.Secondary}
	}
	return []ElementType{ec.Primary}
}

// 缓存键
func (ec *ElementCombination) CacheKey() string {
	return fmt.Sprintf("id_%d", ec.ID)
}

// 字符串展示
func (ec *ElementCombination) String() string {
	if ec.IsDual() {
		return fmt.Sprintf("(%v, %v)", ec.Primary, *ec.Secondary)
	}
	return fmt.Sprintf("(%vv)", ec.Primary)
}

// 元素计算器（全属性支持+缓存）
type ElementCalculator struct {
	tableMatrix     map[ElementType]map[ElementType]float64 // 单属性克制矩阵（全属性）
	offensiveCache  map[string]float64                      // 攻击缓存：X→Y
	combinationPool map[int]*ElementCombination             // 组合池
	mu              sync.RWMutex                            // 并发锁
}

// 创建计算器实例
func NewElementCalculator() *ElementCalculator {
	return &ElementCalculator{
		tableMatrix:     initFullTableMatrix(), // 初始化全属性矩阵
		offensiveCache:  make(map[string]float64),
		combinationPool: make(map[int]*ElementCombination),
	}
}

// 初始化全属性克制矩阵（经双向结果验证）
func initFullTableMatrix() map[ElementType]map[ElementType]float64 {
	// 初始化17×17矩阵，默认系数1.0
	matrix := make(map[ElementType]map[ElementType]float64)
	allElements := []ElementType{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}
	for _, x := range allElements {
		matrix[x] = make(map[ElementType]float64)
		for _, y := range allElements {
			matrix[x][y] = 1.0
		}
	}

	matrix[1][1] = 0.5  // 草→草
	matrix[1][2] = 0.5  // 草→水
	matrix[1][3] = 2.0  // 草→火
	matrix[1][4] = 2.0  // 草→飞行
	matrix[1][5] = 0.5  // 草→电
	matrix[1][7] = 0.5  // 草→地面
	matrix[1][9] = 2.0  // 草→冰
	matrix[1][12] = 0.0 // 草→光（免疫）
	matrix[1][15] = 0.5 // 草→龙
	matrix[1][16] = 2.0 // 草→圣灵

	matrix[2][1] = 2.0  // 水→草
	matrix[2][2] = 0.5  // 水→水
	matrix[2][3] = 0.5  // 水→火
	matrix[2][5] = 2.0  // 水→电
	matrix[2][6] = 0.5  // 水→机械
	matrix[2][9] = 0.5  // 水→冰
	matrix[2][15] = 0.5 // 水→龙
	matrix[2][16] = 2.0 // 水→圣灵

	matrix[3][1] = 0.5  // 火→草
	matrix[3][2] = 2.0  // 火→水
	matrix[3][3] = 0.5  // 火→火
	matrix[3][6] = 0.5  // 火→机械
	matrix[3][7] = 2.0  // 火→地面
	matrix[3][9] = 0.5  // 火→冰
	matrix[3][15] = 0.5 // 火→龙
	matrix[3][16] = 2.0 // 火→圣灵

	// 飞行系
	matrix[4][1] = 2    //飞行->草
	matrix[4][5] = 0.5  //飞行->电
	matrix[4][6] = 0.5  //飞行->机械
	matrix[4][11] = 2   //飞行->战斗
	matrix[4][17] = 0.5 //飞行->次元

	//电系
	matrix[5][1] = 0.5  //电->草
	matrix[5][2] = 2    //电->水
	matrix[5][4] = 2    //电->飞行
	matrix[5][5] = 0.5  //电->电
	matrix[5][7] = 0    //电->地面
	matrix[5][13] = 2   //电->暗影
	matrix[5][14] = 0.5 //电->神秘
	matrix[5][16] = 0.5 //电->圣灵
	matrix[5][17] = 2   //电->次元

	//机械
	matrix[6][2] = 0.5  //机械->水
	matrix[6][3] = 0.5  //机械->火
	matrix[6][5] = 0.5  //机械->电
	matrix[6][6] = 0.5  //机械->机械
	matrix[6][9] = 2    //机械->冰
	matrix[6][11] = 2   //机械->战斗
	matrix[6][17] = 0.5 //机械->次元

	matrix[7][1] = 0.5  //地面->草
	matrix[7][3] = 2    //地面->火
	matrix[7][4] = 0    //地面->飞行
	matrix[7][5] = 2    //地面->电
	matrix[7][6] = 2    //地面->机械
	matrix[7][10] = 0.5 //地面->超能
	matrix[7][13] = 0.5 //地面->暗影
	matrix[7][15] = 0.5 //地面->龙
	matrix[7][16] = 0.5 //地面->圣灵

	matrix[9][1] = 2    //->草
	matrix[9][2] = 0.5  //->水
	matrix[9][3] = 0.5  //->火
	matrix[9][4] = 2    //->飞行
	matrix[9][6] = 0.5  //->机械
	matrix[9][7] = 2    //->地面
	matrix[9][9] = 0.5  //->冰
	matrix[9][16] = 0.5 //->圣灵
	matrix[9][17] = 2   //->次元

	matrix[10][6] = 0.5  //->机械
	matrix[10][10] = 0.5 //->超能
	matrix[10][11] = 2   //->战斗
	matrix[10][12] = 0   //->光
	matrix[10][14] = 2   //->神秘

	matrix[11][6] = 2    //->机械
	matrix[11][9] = 2    //->冰
	matrix[11][10] = 0.5 //->超能
	matrix[11][11] = 0.5 //->战斗
	matrix[11][13] = 0.5 //->暗影
	matrix[11][15] = 2   //->龙
	matrix[11][16] = 2   //->圣灵

	matrix[12][1] = 0    //
	matrix[12][6] = 0.5  //
	matrix[12][9] = 0.5  //
	matrix[12][10] = 2   //
	matrix[12][12] = 0.5 //
	matrix[12][13] = 2   //
	matrix[12][16] = 0.5 //

	matrix[13][6] = 0.5  //
	matrix[13][9] = 0.5  //
	matrix[13][10] = 2   //
	matrix[13][12] = 0.5 //
	matrix[13][13] = 2   //
	matrix[13][16] = 0.5 //
	matrix[13][17] = 2   //

	matrix[14][5] = 2    //->电
	matrix[14][7] = 0.5  //->地面
	matrix[14][11] = 0.5 //->战斗
	matrix[14][14] = 2   //->神秘
	matrix[14][16] = 2   //->圣灵

	matrix[15][1] = 0.5 //->草
	matrix[15][2] = 0.5 //->水
	matrix[15][3] = 0.5 //->火
	matrix[15][5] = 0.5 //->电
	matrix[15][9] = 2   //->冰
	matrix[15][15] = 2  //->龙
	matrix[15][16] = 2  //->圣灵

	matrix[16][1] = 2    //->草
	matrix[16][2] = 2    //->水
	matrix[16][3] = 2    //->火
	matrix[16][5] = 2    //->电
	matrix[16][9] = 2    //->冰
	matrix[16][11] = 0.5 //->战斗
	matrix[16][14] = 0.5 //->神秘
	matrix[16][15] = 0.5 //->龙

	matrix[17][4] = 2   //->飞行
	matrix[17][6] = 2   //->机械
	matrix[17][9] = 0.5 //->冰
	matrix[17][10] = 2  //->超能
	matrix[17][13] = 0  //->暗影

	return matrix
}

// 获取元素组合
func (c *ElementCalculator) GetCombination(id int) (*ElementCombination, error) {
	c.mu.RLock()
	if combo, exists := c.combinationPool[id]; exists {
		c.mu.RUnlock()
		return combo, nil
	}
	c.mu.RUnlock()

	c.mu.Lock()
	defer c.mu.Unlock()
	if combo, exists := c.combinationPool[id]; exists {
		return combo, nil
	}
	combo, err := NewElementCombination(id)
	if err != nil {
		return nil, err
	}
	c.combinationPool[id] = combo
	return combo, nil
}

// 计算攻击方X→防御方Y的系数
func (c *ElementCalculator) GetOffensiveMultiplier(attackerXID, defenderYID int) (float64, error) {
	attackerX, err := c.GetCombination(attackerXID)
	if err != nil {
		return 0, fmt.Errorf("攻击方无效: %v", err)
	}
	defenderY, err := c.GetCombination(defenderYID)
	if err != nil {
		return 0, fmt.Errorf("防御方无效: %v", err)
	}

	cacheKey := fmt.Sprintf("X%d→Y%d", attackerXID, defenderYID)
	c.mu.RLock()
	if val, exists := c.offensiveCache[cacheKey]; exists {
		c.mu.RUnlock()
		return val, nil
	}
	c.mu.RUnlock()

	result := c.calculateMultiplier(attackerX, defenderY)
	c.mu.Lock()
	c.offensiveCache[cacheKey] = result
	c.mu.Unlock()
	return result, nil
}

// 核心计算逻辑（严格遵循橙汁学姐规则）
func (c *ElementCalculator) calculateMultiplier(attackerX, defenderY *ElementCombination) float64 {
	// 1. 单属性→单属性：直接查表
	if !attackerX.IsDual() && !defenderY.IsDual() {
		return c.tableMatrix[attackerX.Primary][defenderY.Primary]
	}

	// 2. 单属性→双属性：拆分防守方，分类计算
	if !attackerX.IsDual() {
		y1, y2 := defenderY.Primary, *defenderY.Secondary
		m1 := c.tableMatrix[attackerX.Primary][y1]
		m2 := c.tableMatrix[attackerX.Primary][y2]

		// 单→双规则：双克制=4，含无效÷4，其他÷2
		if m1 == 2 && m2 == 2 {
			return 4.0
		} else if m1 == 0 || m2 == 0 {
			return (m1 + m2) / 4.0
		} else {
			return (m1 + m2) / 2.0
		}
	}

	// 3. 双属性→单属性：拆分攻击方，分类计算
	if !defenderY.IsDual() {
		x1, x2 := attackerX.Primary, *attackerX.Secondary
		k1 := c.tableMatrix[x1][defenderY.Primary]
		k2 := c.tableMatrix[x2][defenderY.Primary]

		// 补全默认值（未定义的普通关系为1.0）
		if k1 == 0 && c.tableMatrix[x1][defenderY.Primary] != 0 {
			k1 = 1.0
		}
		if k2 == 0 && c.tableMatrix[x2][defenderY.Primary] != 0 {
			k2 = 1.0
		}

		// 双→单规则：双克制=4，含无效÷4，其他÷2
		if k1 == 2 && k2 == 2 {
			return 4.0
		} else if k1 == 0 || k2 == 0 {
			return (k1 + k2) / 4.0
		} else {
			return (k1 + k2) / 2.0
		}
	}

	// 4. 双属性→双属性：拆分防守方为两个单属性，分别计算双→单后取平均
	x1, x2 := attackerX.Primary, *attackerX.Secondary
	y1, y2 := defenderY.Primary, *defenderY.Secondary

	// 计算攻击方对防守方第一个单属性（y1）的双→单系数
	coeffY1 := c.calculateDualToSingle(x1, x2, y1)
	// 计算攻击方对防守方第二个单属性（y2）的双→单系数
	coeffY2 := c.calculateDualToSingle(x1, x2, y2)

	// 双→双最终系数 = 两个双→单系数的平均值
	return (coeffY1 + coeffY2) / 2.0
}

// 辅助函数：双属性攻击单属性的核心计算（提取复用逻辑）
func (c *ElementCalculator) calculateDualToSingle(attacker1, attacker2, defender ElementType) float64 {
	k1 := c.tableMatrix[attacker1][defender]
	k2 := c.tableMatrix[attacker2][defender]

	// 补全默认值（未定义的普通关系为1.0）
	if k1 == 0 && c.tableMatrix[attacker1][defender] != 0 {
		k1 = 1.0
	}
	if k2 == 0 && c.tableMatrix[attacker2][defender] != 0 {
		k2 = 1.0
	}

	// 双→单规则应用
	if k1 == 2 && k2 == 2 {
		return 4.0
	} else if k1 == 0 || k2 == 0 {
		return (k1 + k2) / 4.0
	} else {
		return (k1 + k2) / 2.0
	}
}

// 全场景测试用例
func TestAllScenarios(t *testing.T) {
	calculator := NewElementCalculator()

	// 测试1：单属性→单属性（草→水）
	m1, _ := calculator.GetOffensiveMultiplier(1, 2)
	t.Logf("草→水: %.2f（预期2.0）", m1)
	if math.Abs(m1-2.0) > 0.001 {
		t.Errorf("测试1错误: 实际%.2f", m1)
	}

	// 测试2：单属性→双属性（火→冰龙）
	m2, _ := calculator.GetOffensiveMultiplier(3, 43) // 火→冰龙(9+15)
	// 火→冰=2.0，火→龙=1.0 → 平均值=1.5
	t.Logf("火→冰龙: %.2f（预期1.5）", m2)
	if math.Abs(m2-1.5) > 0.001 {
		t.Errorf("测试2错误: 实际%.2f", m2)
	}

	// 测试3：双属性→单属性（飞行超能→草）
	m3, _ := calculator.GetOffensiveMultiplier(30, 1) // 飞行超能→草
	// 飞行→草=2.0，超能→草=1.0 → 平均值=1.5
	t.Logf("飞行超能→草: %.2f（预期1.5）", m3)
	if math.Abs(m3-1.5) > 0.001 {
		t.Errorf("测试3错误: 实际%.2f", m3)
	}

	// 测试4：双属性→双属性（冰暗影→电战斗）预期=1.0
	m4, _ := calculator.GetOffensiveMultiplier(45, 35)
	// 冰→电=1.0，冰→战斗=0.5，暗影→电=0.5，暗影→战斗=2.0 → 总和=4.0 → 平均值=1.0
	t.Logf("冰暗影→电战斗: %.4f（预期1.0）", m4)
	if math.Abs(m4-1.0) > 0.001 {
		t.Errorf("测试4错误: 实际%.4f", m4)
	}

	// 测试5：双属性→双属性（电战斗→冰暗影）预期=1.375
	m5, _ := calculator.GetOffensiveMultiplier(35, 45)
	// 电→冰=1.0，电→暗影=1.0，战斗→冰=2.0，战斗→暗影=1.5 → 总和=5.5 → 平均值=1.375
	t.Logf("电战斗→冰暗影: %.4f（预期1.375）", m5)
	if math.Abs(m5-1.375) > 0.001 {
		t.Errorf("测试5错误: 实际%.4f", m5)
	}

	// 测试6：特殊免疫（飞行→地面）
	m6, _ := calculator.GetOffensiveMultiplier(4, 7)
	t.Logf("飞行→地面: %.2f（预期0.0）", m6)
	if math.Abs(m6-0.0) > 0.001 {
		t.Errorf("测试6错误: 实际%.2f", m6)
	}

	// 测试7：光暗影→暗影（光→暗影=2.0，暗影→暗影=1.0 → 平均值=1.5）
	m7, _ := calculator.GetOffensiveMultiplier(69, 13)
	t.Logf("光暗影→暗影: %.2f（预期1.5）", m7)
	if math.Abs(m7-1.5) > 0.001 {
		t.Errorf("测试7错误: 实际%.2f", m7)
	}

	// 测试8：缓存验证（复用测试4结果）
	m8, _ := calculator.GetOffensiveMultiplier(46, 25)
	if m8 != m4 {
		t.Error("测试8错误: 缓存未命中")
	}
}
