import { _decorator, Vec3, math } from "cc";
import { Snake } from "../Snake";
import { AIBehaviorParams } from "./AIBehaviorParams";
import { AIState } from "./AIState";
import { DecisionResult } from "./AIDecision";
import { Global } from "../Global";
import { MainGame } from "../MainGame";

const { ccclass, property } = _decorator;

@ccclass("AIMovement")
export class AIMovement {

    private readonly SAFE_MARGIN = 3.0; // 增加安全边际
    private readonly OBSTACLE_CHECK_DISTANCE = 250; // 增加检测距离
    private readonly AVOIDANCE_TURN_SPEED = 8; // 提高基础转向速度
    private readonly EMERGENCY_TURN_SPEED = 12; // 提高紧急转向速度
    private readonly PREDICTION_STEPS = 5; // 减少预测步数以加快反应
    private readonly ESCAPE_BOUNDARY = 180; // 增加边界安全距离

    constructor(
        private snake: Snake,
        private params: AIBehaviorParams
    ) { }

    execute(decision: DecisionResult) {
        // 更新速度
        this.snake.moveScale = decision.moveSpeed;
        this.snake.isFast = decision.shouldBoost;

        // 执行对应状态的移动
        switch (decision.targetState) {
            case AIState.HUNTING:
                this.executeHunting(decision);
                break;
            case AIState.INTERCEPTING:
                this.executeIntercepting(decision);
                break;
            case AIState.ESCAPING:
                this.executeEscaping(decision);
                break;
            case AIState.WANDERING:
                this.executeWandering(decision);
                break;
            case AIState.ASSISTING:
                this.executeAssisting(decision);
                break;
        }
    }

    private executeHunting(decision: DecisionResult) {
        if (!decision.targetPosition) return;
        this.smoothRotateToTarget(decision.targetPosition);
    }

    private executeIntercepting(decision: DecisionResult) {
        if (!decision.targetSnake?.isLife) return;
        const predictedPos = this.predictTargetPosition(decision.targetSnake);
        this.smoothRotateToTarget(predictedPos);
    }

    private executeEscaping(decision: DecisionResult) {
        if (!decision.targetPosition) return;
        this.smoothRotateToTarget(decision.targetPosition);
    }

    private executeWandering(decision: DecisionResult) {
        if (!decision.targetPosition) return;
        this.smoothRotateToTarget(decision.targetPosition);
    }

    private executeAssisting(decision: DecisionResult) {
        if (!decision.targetPosition) return;
        this.smoothRotateToTarget(decision.targetPosition);
    }


    private smoothRotateToTarget(targetPos: Vec3) {
        const targetAngle = this.calculateTargetAngle(targetPos);
        const obstacleCheck = this.predictObstacles(targetAngle);
        const currentAngle = this.snake.head.angle;
        
        let angleDiff = targetAngle - currentAngle;
        while (angleDiff > 180) angleDiff -= 360;
        while (angleDiff < -180) angleDiff += 360;
    
        if (obstacleCheck.hasObstacle) {
            // 立即转向，不再添加随机性
            const turnSpeed = obstacleCheck.dangerLevel >= 0.6 ? // 降低危险阈值
                this.EMERGENCY_TURN_SPEED : 
                this.AVOIDANCE_TURN_SPEED;
                
            // 直接使用最佳转向角度
            this.snake.head.angle = obstacleCheck.bestAngle;
            
            // 危险时立即减速
            this.snake.moveScale *= 0.5;
        } else {
            const turnSpeed = this.params.params.turnSpeed;
            const maxTurn = Math.min(Math.abs(angleDiff), turnSpeed * 1.5);
            this.snake.head.angle += Math.sign(angleDiff) * maxTurn;
        }
    }

    private predictObstacles(targetAngle: number): {
        hasObstacle: boolean;
        bestAngle: number;
        dangerLevel: number;
        turnDirection: number;
    } {
        const myPos = this.snake.head.getPosition();
        const myAngle = this.snake.head.angle;

        let minDanger = Infinity;
        let bestAngle = myAngle;
        let bestTurnDir = 0;

        // 检查更多角度
        const checkAngles = [-90, -60, -45, -30, -15, 0, 15, 30, 45, 60, 90];

        for (const angleOffset of checkAngles) {
            let currentPos = myPos.clone();
            let currentAngle = myAngle + angleOffset;
            let maxDanger = 0;
            let totalDanger = 0;

            // 多步预测
            for (let step = 1; step <= this.PREDICTION_STEPS; step++) {
                const radian = currentAngle * Math.PI / 180;
                const stepDistance = this.OBSTACLE_CHECK_DISTANCE / this.PREDICTION_STEPS;

                const stepVector = new Vec3(
                    Math.cos(radian) * stepDistance,
                    Math.sin(radian) * stepDistance,
                    0
                );
                currentPos.add(stepVector);

                // 计算边界危险度
                const mapHalfWidth = Global.MAP_WIDTH / 2;
                const mapHalfHeight = Global.MAP_HEIGHT / 2;

                const boundaryDanger = Math.max(
                    Math.max(0, (Math.abs(currentPos.x) - (mapHalfWidth - this.ESCAPE_BOUNDARY)) / this.ESCAPE_BOUNDARY),
                    Math.max(0, (Math.abs(currentPos.y) - (mapHalfHeight - this.ESCAPE_BOUNDARY)) / this.ESCAPE_BOUNDARY)
                );

                // 计算其他蛇的危险度
                const obstacleDistance = this.getObstacleDistance(myPos, currentPos);
                const obstacleDanger = Math.max(0, 1 - obstacleDistance / (this.OBSTACLE_CHECK_DISTANCE * this.SAFE_MARGIN));

                const stepDanger = Math.max(boundaryDanger * 1.5, obstacleDanger);
                maxDanger = Math.max(maxDanger, stepDanger);
                totalDanger += stepDanger * (1 - step / this.PREDICTION_STEPS);
            }

            // 考虑与目标角度的差异
            const angleDiff = Math.abs(currentAngle - targetAngle);
            const angleWeight = 1 - (angleDiff / 180) * 0.5;

            const finalDanger = maxDanger * 0.7 + (totalDanger / this.PREDICTION_STEPS) * 0.3;
            const weightedDanger = finalDanger / angleWeight;

            if (weightedDanger < minDanger) {
                minDanger = weightedDanger;
                bestAngle = currentAngle;
                bestTurnDir = angleOffset;
            }
        }

        return {
            hasObstacle: minDanger > 0.2, // 降低危险阈值，更早触发避障
            bestAngle: bestAngle,
            dangerLevel: minDanger,
            turnDirection: bestTurnDir
        };
    }

    private calculateTargetAngle(targetPos: Vec3): number {
        const myPos = this.snake.head.getPosition();
        return math.toDegree(Math.atan2(
            targetPos.y - myPos.y,
            targetPos.x - myPos.x
        ));
    }

    private getObstacleDistance(from: Vec3, to: Vec3): number {
        // 检查地图边界
        const mapHalfWidth = Global.MAP_WIDTH / 2;
        const mapHalfHeight = Global.MAP_HEIGHT / 2;
        const margin = 50;

        if (Math.abs(to.x) > mapHalfWidth - margin ||
            Math.abs(to.y) > mapHalfHeight - margin) {
            return 0;
        }

        // 检查蛇身碰撞
        let minDistance = this.OBSTACLE_CHECK_DISTANCE;
        const competitors = MainGame.ins.animalNode.children;

        for (const competitor of competitors) {
            const snake = competitor.getComponent(Snake);
            if (!snake?.isLife || snake === this.snake) continue;

            // 检查头部碰撞
            const headDistance = Vec3.distance(to, snake.head.getPosition());
            minDistance = Math.min(minDistance, headDistance);

            // 检查身体碰撞
            for (let i = 1; i < snake.bodyArr.length; i += 2) {
                const bodyPart = snake.bodyArr[i];
                const bodyDistance = Vec3.distance(to, bodyPart.getPosition());
                minDistance = Math.min(minDistance, bodyDistance);
            }
        }

        return minDistance;
    }

    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 * this.params.params.predictionAccuracy;
        const predictY = targetPos.y + Math.sin(radian) * targetSpeed * this.params.PREDICTION_TIME * this.params.params.predictionAccuracy;

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