import { _decorator, Component, input, Input, EventTouch, Camera, Node, Vec3, UITransform, math } from 'cc';
const { ccclass, property } = _decorator;

interface NodeCell {
  x: number;
  y: number;
  g: number;
  h: number;
  f: number;
  parent?: NodeCell;
}

@ccclass('GameController')
export class GameController extends Component {
  @property(Camera)
  camera: Camera = null!;

  @property(Node)
  player: Node = null!;

  @property(Node)
  map: Node = null!;

  @property
  gridSize: number = 32;

  @property
  moveSpeed: number = 200;

  @property
  camSmooth: number = 5;

  private mapData: number[][] = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
    [0, 1, 0, 0, 0, 1, 1, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
  ];

  private path: Vec3[] = [];
  private camPos: Vec3 = new Vec3();
  private mapSize: Vec3 = new Vec3();

  onLoad() {
    input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);

    // 获取地图大小
    const ui = this.map.getComponent(UITransform);
    if (ui) {
      this.mapSize.set(ui.width, ui.height, 0);
    }
  }

  onDestroy() {
    input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
  }

  // 点击地图 -> 计算寻路路径
  onTouchEnd(event: EventTouch) {
    if (!this.camera) return;

    const screenPos = event.getLocation();
    const worldPos = this.camera.screenToWorld(new Vec3(screenPos.x, screenPos.y, 0));

    const startCell = this.worldToCell(this.player.getWorldPosition());
    const endCell = this.worldToCell(worldPos);

    const cellPath = this.findPath(startCell, endCell);
    if (cellPath.length > 0) {
      this.path = cellPath.map(c => this.cellToWorld(c));
    }
  }

  update(deltaTime: number) {
    // === 角色移动 ===
    if (this.path.length > 0) {
      const pos = this.player.getWorldPosition();
      const target = this.path[0];
      const dir = target.subtract(pos);
      const dist = dir.length();

      if (dist < this.moveSpeed * deltaTime) {
        this.player.setWorldPosition(target);
        this.path.shift();
      } else {
        dir.normalize();
        const move = dir.multiplyScalar(this.moveSpeed * deltaTime);
        this.player.setWorldPosition(pos.add(move));
      }
    }

    // === 相机跟随 ===
    const targetPos = this.player.getWorldPosition();
    const desiredPos = new Vec3(targetPos.x, targetPos.y, 1000); // Z 拉远
    Vec3.lerp(this.camPos, this.camera.node.getWorldPosition(), desiredPos, deltaTime * this.camSmooth);

    // 限制相机范围
    const halfW = this.mapSize.x / 2;
    const halfH = this.mapSize.y / 2;
    const viewW = 400; // 你可以用实际相机视口宽高
    const viewH = 300;

    this.camPos.x = math.clamp(this.camPos.x, -halfW + viewW, halfW - viewW);
    this.camPos.y = math.clamp(this.camPos.y, -halfH + viewH, halfH - viewH);

    this.camera.node.setWorldPosition(this.camPos);
  }

  // ============ A* 寻路实现 ============

  worldToCell(worldPos: Vec3): { x: number, y: number } {
    return {
      x: Math.floor(worldPos.x / this.gridSize),
      y: Math.floor(worldPos.y / this.gridSize),
    };
  }

  cellToWorld(cell: { x: number, y: number }): Vec3 {
    return new Vec3(
      cell.x * this.gridSize + this.gridSize / 2,
      cell.y * this.gridSize + this.gridSize / 2,
      0
    );
  }

  findPath(start: { x: number, y: number }, end: { x: number, y: number }): { x: number, y: number }[] {
    const open: NodeCell[] = [];
    const closed: boolean[][] = [];
    const rows = this.mapData.length;
    const cols = this.mapData[0].length;

    function heuristic(a: { x: number, y: number }, b: { x: number, y: number }) {
      return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
    }

    open.push({ x: start.x, y: start.y, g: 0, h: heuristic(start, end), f: 0 });

    while (open.length > 0) {
      open.sort((a, b) => (a.g + a.h) - (b.g + b.h));
      const current = open.shift()!;
      closed[current.y] = closed[current.y] || [];
      closed[current.y][current.x] = true;

      if (current.x === end.x && current.y === end.y) {
        const path: { x: number, y: number }[] = [];
        let node: NodeCell | undefined = current;
        while (node) {
          path.unshift({ x: node.x, y: node.y });
          node = node.parent;
        }
        return path;
      }

      const neighbors = [
        { x: current.x + 1, y: current.y },
        { x: current.x - 1, y: current.y },
        { x: current.x, y: current.y + 1 },
        { x: current.x, y: current.y - 1 },
      ];

      for (const n of neighbors) {
        if (n.x < 0 || n.y < 0 || n.y >= rows || n.x >= cols) continue;
        if (this.mapData[n.y][n.x] === 1) continue;
        if (closed[n.y]?.[n.x]) continue;

        const g = current.g + 1;
        const h = heuristic(n, end);
        const existing = open.find(o => o.x === n.x && o.y === n.y);
        if (!existing || g < existing.g) {
          open.push({ x: n.x, y: n.y, g, h, f: g + h, parent: current });
        }
      }
    }
    return [];
  }
}
