import { _decorator, Vec3, math } from "cc";
import { AIBehaviorParams } from "./AIBehaviorParams";
import { PerceptionResult } from "./AIPerception";
import { Snake } from "../Snake";
import { AIState } from "./AIState";
import { Global } from "../Global";


const { ccclass, property } = _decorator;

export interface DecisionResult {
    targetState: AIState;
    targetPosition: Vec3 | null;
    moveSpeed: number;
    shouldBoost: boolean;
    targetSnake: Snake | null;
    assistPartner: Snake | null;
}
@ccclass("AIDecision")
export class AIDecision {
    private readonly DANGER_THRESHOLD = 0.5;
    private readonly LENGTH_ADVANTAGE_THRESHOLD = 1.8;
    private readonly SAFE_DISTANCE = 200;
    private readonly HUNTING_RANGE = 400;
    private readonly MIN_HUNTING_SCORE = 0.2;

    constructor(private params: AIBehaviorParams) { }

    makeDecision(perception: PerceptionResult): DecisionResult {
        // 计算综合评分
        const scores = this.calculateActionScores(perception);

        // 选择得分最高的行为
        const bestAction = this.selectBestAction(scores);

        // 执行对应的决策
        switch (bestAction) {
            case 'escape': return this.makeEscapeDecision(perception);
            case 'hunt': return this.makeHuntingDecision(perception);
            case 'attack': return this.makeAttackDecision(perception);
            case 'assist': return this.makeAssistDecision(perception);
            default: return this.makeWanderingDecision(perception);
        }
    }


    private calculateActionScores(perception: PerceptionResult): Record<string, number> {
        const scores: Record<string, number> = {
            escape: this.calculateEscapeScore(perception),
            hunt: this.calculateHuntingScore(perception),
            attack: this.calculateAttackScore(perception),
            assist: this.calculateAssistScore(perception),
            wander: 0.2
        };

        this.adjustScoresBasedOnSituation(scores, perception);
        return scores;
    }


    private calculateEscapeScore(perception: PerceptionResult): number {
        let score = 0;
        const myPos = perception.snake.head.getPosition();
    
        // 更自然的危险评估
        if (perception.dangerLevel > this.DANGER_THRESHOLD) {
            // 不会过度恐慌，而是根据实力比例来判断
            const panicFactor = perception.powerRatio < 0.7 ? 1.2 : 0.8;
            score = 0.7 + perception.dangerLevel * 0.3 * panicFactor;
        }
    
        // 更智能的边界处理
        if (perception.boundaryDistance < this.params.ESCAPE_BOUNDARY) {
            const boundaryFactor = perception.boundaryDistance / this.params.ESCAPE_BOUNDARY;
            // 靠近边界时会提前转向，而不是等到最后一刻
            score += (1 - Math.pow(boundaryFactor, 2)) * 0.6;
        }
    
        // 更自然的威胁反应
        if (perception.nearestThreat) {
            const distanceToThreat = Vec3.distance(myPos, perception.nearestThreat.head.getPosition());
            const threatLength = perception.nearestThreat.getSnakeLen();
            const myLength = perception.snake.getSnakeLen();
            
            // 根据体型差异调整反应
            const lengthRatio = myLength / threatLength;
            if (lengthRatio < 0.8) {
                // 弱势时更容易逃跑
                score += (1 - distanceToThreat / (this.SAFE_DISTANCE * 2)) * 0.7;
            } else if (lengthRatio < 1.2) {
                // 势均力敌时保持警惕但不会过度逃避
                score += (1 - distanceToThreat / (this.SAFE_DISTANCE * 1.5)) * 0.4;
            }
        }
    
        return Math.min(score, 1);
    }


    private calculateHuntingScore(perception: PerceptionResult): number {
        if (!perception.nearestFood) return this.MIN_HUNTING_SCORE;

        const distanceToFood = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.nearestFood
        );

        if (distanceToFood > this.HUNTING_RANGE) return this.MIN_HUNTING_SCORE;

        let score = (1 - distanceToFood / this.HUNTING_RANGE) * 
            (1 - perception.dangerLevel * 0.5) * 1.2;

        // 近距离食物加分
        if (distanceToFood < this.HUNTING_RANGE * 0.3) {
            score += 0.3;
        }

        // 根据局势调整
        score *= (1 + perception.territoryControl * 0.3);
        score *= (1 + perception.powerRatio * 0.2);

        return Math.min(score, 1);
    }

    private calculateAttackScore(perception: PerceptionResult): number {
        if (!perception.player?.isLife || perception.dangerLevel > 0.3) return 0;

        const myLength = perception.snake.getSnakeLen();
        const playerLength = perception.player.getSnakeLen();
        
        if (myLength <= playerLength * this.LENGTH_ADVANTAGE_THRESHOLD) return 0;

        const distanceToPlayer = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.player.head.getPosition()
        );

        let score = (1 - perception.dangerLevel) * 
            (myLength / playerLength - this.LENGTH_ADVANTAGE_THRESHOLD) * 
            (1 - distanceToPlayer / this.params.params.viewDistance) * 0.4;

        // 根据局势调整
        score *= perception.territoryControl;
        score *= perception.powerRatio * 0.5;

        return Math.min(score, 1);
    }

    private calculateAssistScore(perception: PerceptionResult): number {
        if (!perception.assistPartner || !perception.player?.isLife || 
            perception.dangerLevel > 0.3) return 0;

        const combinedLength = perception.snake.getSnakeLen() + 
            perception.assistPartner.getSnakeLen();
        const playerLength = perception.player.getSnakeLen();

        if (combinedLength <= playerLength * 1.5) return 0;

        const distance = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.assistPartner.head.getPosition()
        );

        let score = (1 - perception.dangerLevel) * 
            (combinedLength / playerLength - 1.5) * 
            (1 - distance / this.params.params.viewDistance) * 0.4;

        score *= perception.territoryControl;
        return Math.min(score, 1);
    }

    private adjustScoresBasedOnSituation(
        scores: Record<string, number>, 
        perception: PerceptionResult
    ): void {
        // 根据局势调整行为权重
        if (perception.powerRatio > 1.5 && perception.territoryControl > 0.6) {
            scores.hunt *= 1.3;
            scores.attack *= 1.2;
        } else if (perception.powerRatio < 0.7 || perception.territoryControl < 0.3) {
            scores.escape *= 1.4;
            scores.wander *= 1.2;
        }

        // 标准化分数
        const total = Object.values(scores).reduce((a, b) => a + b, 0);
        if (total > 0) {
            for (const key in scores) {
                scores[key] /= total;
            }
        }
    }
    
    private selectBestAction(scores: Record<string, number>): string {
        let bestAction = 'wander';
        let bestScore = scores.wander;

        for (const [action, score] of Object.entries(scores)) {
            if (score > bestScore) {
                bestScore = score;
                bestAction = action;
            }
        }

        return bestAction;
    }

    private makeEscapeDecision(perception: PerceptionResult): DecisionResult {
        const escapePos = this.calculateEscapePosition(perception);
        return {
            targetState: AIState.ESCAPING,
            targetPosition: escapePos,
            moveSpeed: 1,
            shouldBoost: true,
            targetSnake: perception.nearestThreat,
            assistPartner: null
        };
    }

    private makeAttackDecision(perception: PerceptionResult): DecisionResult {
        return {
            targetState: AIState.INTERCEPTING,
            targetPosition: this.predictTargetPosition(perception.player),
            moveSpeed: 1,
            shouldBoost: this.shouldBoostForAttack(perception),
            targetSnake: perception.player,
            assistPartner: null
        };
    }

    private makeAssistDecision(perception: PerceptionResult): DecisionResult {
        return {
            targetState: AIState.ASSISTING,
            targetPosition: this.calculateAssistPosition(perception),
            moveSpeed: 1,
            shouldBoost: this.shouldBoostForAssist(perception),
            targetSnake: perception.player,
            assistPartner: perception.assistPartner
        };
    }

    private makeHuntingDecision(perception: PerceptionResult): DecisionResult {
        return {
            targetState: AIState.HUNTING,
            targetPosition: perception.nearestFood,
            moveSpeed: this.calculateHuntingSpeed(perception),
            shouldBoost: this.shouldBoostForHunting(perception), // 新增加速判断
            targetSnake: null,
            assistPartner: null
        };
    }

    // 新增觅食加速判断
    private shouldBoostForHunting(perception: PerceptionResult): boolean {
        if (!perception.nearestFood) return false;

        const distanceToFood = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.nearestFood
        );

        // 当食物较近且危险程度较低时加速
        return distanceToFood < this.HUNTING_RANGE * 0.4 && 
               perception.dangerLevel < 0.3;
    }

    private makeWanderingDecision(perception: PerceptionResult): DecisionResult {
        // 游走时远离玩家
        const wanderPos = this.calculateWanderPosition(perception);
        if (perception.player?.isLife) {
            const playerPos = perception.player.head.getPosition();
            const myPos = perception.snake.head.getPosition();
            if (Vec3.distance(myPos, playerPos) < this.SAFE_DISTANCE * 2) {
                // 远离玩家的方向游走
                const awayFromPlayer = new Vec3(
                    myPos.x - playerPos.x,
                    myPos.y - playerPos.y,
                    0
                ).normalize();
                wanderPos.x = myPos.x + awayFromPlayer.x * this.params.params.viewDistance * 0.7;
                wanderPos.y = myPos.y + awayFromPlayer.y * this.params.params.viewDistance * 0.7;
            }
        }

        return {
            targetState: AIState.WANDERING,
            targetPosition: wanderPos,
            moveSpeed: 0.8,
            shouldBoost: false,
            targetSnake: null,
            assistPartner: null
        };
    }

    private calculateEscapePosition(perception: PerceptionResult): Vec3 {
        const myPos = perception.snake.head.getPosition();
        let escapeVector = new Vec3();

        // 考虑边界威胁
        if (perception.boundaryDistance < this.params.ESCAPE_BOUNDARY) {
            escapeVector.add(this.calculateBoundaryEscapeVector(perception));
        }

        // 考虑蛇的威胁
        if (perception.nearestThreat) {
            const threatPos = perception.nearestThreat.head.getPosition();
            const awayFromThreat = new Vec3(
                myPos.x - threatPos.x,
                myPos.y - threatPos.y,
                0
            );
            awayFromThreat.normalize().multiplyScalar(this.params.params.viewDistance);
            escapeVector.add(awayFromThreat);
        }

        // 如果没有明确的逃跑方向，生成随机方向
        if (escapeVector.length() < 0.1) {
            const randomAngle = math.random() * Math.PI * 2;
            escapeVector.set(
                Math.cos(randomAngle) * this.params.params.viewDistance,
                Math.sin(randomAngle) * this.params.params.viewDistance,
                0
            );
        }

        return new Vec3(
            myPos.x + escapeVector.x,
            myPos.y + escapeVector.y,
            0
        );
    }

    private calculateAssistPosition(perception: PerceptionResult): Vec3 {
        const playerPos = perception.player.head.getPosition();
        const partnerPos = perception.assistPartner.head.getPosition();

        // 计算包夹位置
        const angle = math.random() * Math.PI * 2;
        const radius = this.params.params.interceptDistance * 0.7;

        return new Vec3(
            playerPos.x + Math.cos(angle) * radius,
            playerPos.y + Math.sin(angle) * radius,
            0
        );
    }

    private calculateWanderPosition(perception: PerceptionResult): Vec3 {
        const myPos = perception.snake.head.getPosition();
        const targetPos = new Vec3();

        // 计算逃离向量
        const escapeVector = new Vec3();

        // 远离所有威胁
        for (const competitor of perception.nearbyCompetitors) {
            const competitorPos = competitor.head.getPosition();
            const distance = Vec3.distance(myPos, competitorPos);
            if (distance < this.SAFE_DISTANCE * 4) {
                const away = new Vec3(
                    myPos.x - competitorPos.x,
                    myPos.y - competitorPos.y,
                    0
                ).normalize().multiplyScalar(1 / Math.max(distance, 1));
                escapeVector.add(away);
            }
        }

        // 特别远离玩家
        if (perception.player?.isLife) {
            const playerPos = perception.player.head.getPosition();
            const distanceToPlayer = Vec3.distance(myPos, playerPos);
            if (distanceToPlayer < this.SAFE_DISTANCE * 5) {
                const awayFromPlayer = new Vec3(
                    myPos.x - playerPos.x,
                    myPos.y - playerPos.y,
                    0
                ).normalize().multiplyScalar(2 / Math.max(distanceToPlayer, 1));
                escapeVector.add(awayFromPlayer);
            }
        }

        // 如果有逃离方向
        if (escapeVector.length() > 0.1) {
            escapeVector.normalize().multiplyScalar(this.SAFE_DISTANCE * 3);
            targetPos.set(
                myPos.x + escapeVector.x,
                myPos.y + escapeVector.y,
                0
            );
        } else {
            // 随机游走
            const randomAngle = Math.random() * Math.PI * 2;
            const randomDistance = this.SAFE_DISTANCE * (2 + Math.random() * 2);
            targetPos.set(
                myPos.x + Math.cos(randomAngle) * randomDistance,
                myPos.y + Math.sin(randomAngle) * randomDistance,
                0
            );
        }

        // 确保在地图范围内
        const mapHalfWidth = Global.MAP_WIDTH / 2;
        const mapHalfHeight = Global.MAP_HEIGHT / 2;
        const margin = this.SAFE_DISTANCE;

        targetPos.x = math.clamp(targetPos.x, -mapHalfWidth + margin, mapHalfWidth - margin);
        targetPos.y = math.clamp(targetPos.y, -mapHalfHeight + margin, mapHalfHeight - margin);

        return targetPos;
    }

    private predictTargetPosition(target: Snake): Vec3 {
        const targetPos = target.head.getPosition();
        const targetAngle = target.head.angle;
        const targetSpeed = target.isFast ? target.speed * 2 : target.speed;

        const radian = targetAngle * Math.PI / 180;
        const predictX = targetPos.x + Math.cos(radian) * targetSpeed * this.params.PREDICTION_TIME;
        const predictY = targetPos.y + Math.sin(radian) * targetSpeed * this.params.PREDICTION_TIME;

        return new Vec3(predictX, predictY, 0);
    }

    private calculateBoundaryEscapeVector(perception: PerceptionResult): Vec3 {
        const myPos = perception.snake.head.getPosition();
        const escapeVector = new Vec3();
        const mapHalfWidth = Global.MAP_WIDTH / 2;
        const mapHalfHeight = Global.MAP_HEIGHT / 2;

        // 根据到边界的距离计算逃离向量
        if (myPos.x > mapHalfWidth * 0.8) escapeVector.x = -1;
        if (myPos.x < -mapHalfWidth * 0.8) escapeVector.x = 1;
        if (myPos.y > mapHalfHeight * 0.8) escapeVector.y = -1;
        if (myPos.y < -mapHalfHeight * 0.8) escapeVector.y = 1;

        return escapeVector.normalize();
    }

    private shouldBoostForAttack(perception: PerceptionResult): boolean {
        if (!perception.player) return false;

        const distanceToPlayer = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.player.head.getPosition()
        );

        return distanceToPlayer < this.params.params.interceptDistance * 0.7;
    }

    private shouldBoostForAssist(perception: PerceptionResult): boolean {
        if (!perception.player || !perception.assistPartner) return false;

        const distanceToPlayer = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.player.head.getPosition()
        );

        return distanceToPlayer < this.params.params.interceptDistance * 0.5;
    }

    private calculateHuntingSpeed(perception: PerceptionResult): number {
        if (!perception.nearestFood) return 1;

        const distanceToFood = Vec3.distance(
            perception.snake.head.getPosition(),
            perception.nearestFood
        );

        // 调整速度曲线，使其更积极
        return math.lerp(0.9, 1.3, 1 - (distanceToFood / this.HUNTING_RANGE));
    }
} 