// assets/scripts/GameManager.ts
import {
    _decorator,
    Component,
    Node,
    Prefab,
    instantiate,
    NodePool,
    UITransform,
    Vec3,
    v3,
    input,
    Input,
    EventTouch,
    SpriteFrame,
    Sprite,
    Label,
    RigidBody2D,
    Vec2,
    tween,
    AudioSource,
    sys,
    math,
  } from 'cc';
  import { FRUITS, clampLevel, randomStartLevel } from './FruitConfig';
  import { Fruit } from './Fruit';
  const { ccclass, property } = _decorator;
  
  @ccclass('GameManager')
  export class GameManager extends Component {
    @property(Prefab)
    fruitPrefab!: Prefab; // 统一水果预制
  
    @property([SpriteFrame])
    fruitSprites: SpriteFrame[] = []; // 长度需 >= FRUITS.length，按等级顺序
  
    @property(Node)
    fruitRoot!: Node;
  
    @property(Node)
    preview!: Node; // 顶部预览点，挂 Sprite
  
    @property(Node)
    topSensor!: Node; // 仅用于场景绑定与可视化
  
    @property(Node)
    walls!: Node; // Left/Right/Floor（用于取边界宽度，可留空）
  
    @property(Label)
    scoreLabel!: Label;
  
    @property(Label)
    bestLabel!: Label;
  
    @property(Node)
    dropLine!: Node; // 危险红线（可选）
  
    @property(AudioSource)
    sfx!: AudioSource; // 可选
  
    // —— 可调参数 ——
    @property
    previewY = 560; // 预览/下落的 Y（根据分辨率调整）
    @property
    spawnCooldown = 0.2; // 连续投掷冷却
    @property
    previewClampPadding = 40; // 贴边留白
    @property
    randomStartMaxLevel = 5; // 随机初级水果最大等级
  
    // —— 运行时状态 ——
    nextLevel = 1; // 将要投的等级
    queuedLevel = 1; // 下一颗的预告
    canDrop = true;
    isGameOver = false;
    dangerOn = false;
    score = 0;
    best = 0;
  
    private pool = new NodePool();
  
    onLoad() {
      // 把 SpriteFrame 注入配置（可选）
      for (let i = 0; i < FRUITS.length; i++) {
        FRUITS[i].sprite = this.fruitSprites[i] || FRUITS[i].sprite;
      }
      this.best = Number(sys.localStorage.getItem('best') || 0);
      if (this.bestLabel) this.bestLabel.string = `${this.best}`;
      if (this.scoreLabel) this.scoreLabel.string = `0`;
    }
  
    start() {
      this.bindInput();
      this.reset();
    }
  
    protected onDestroy() {
      this.unbindInput();
    }
  
    bindInput() {
      input.on(Input.EventType.TOUCH_MOVE, this.onMove, this);
      input.on(Input.EventType.TOUCH_START, this.onMove, this); // 触摸开始也更新预览位置
      input.on(Input.EventType.TOUCH_END, this.onDrop, this);
    }
  
    unbindInput() {
      input.off(Input.EventType.TOUCH_MOVE, this.onMove, this);
      input.off(Input.EventType.TOUCH_START, this.onMove, this);
      input.off(Input.EventType.TOUCH_END, this.onDrop, this);
    }
  
    reset() {
      this.isGameOver = false;
      this.canDrop = true;
      this.updateScore(0);
  
      // 清场（放回对象池而非直接删）
      const children = [...this.fruitRoot.children];
      for (const c of children) this.recycleFruit(c);
  
      // 初始化两个预报等级
      this.nextLevel = randomStartLevel(1, this.randomStartMaxLevel);
      this.queuedLevel = randomStartLevel(1, this.randomStartMaxLevel);
  
      this.refreshPreview();
      this.setDanger(false);
      if (this.dropLine) this.dropLine.active = false;
    }
  
    refreshPreview() {
      if (!this.preview) return;
      const sp = this.preview.getComponent(Sprite)!;
      const def = FRUITS[this.nextLevel - 1];
      sp.spriteFrame = def.sprite!;
  
      const ui = this.preview.getComponent(UITransform)!;
      ui.setContentSize(def.radius * 2, def.radius * 2);
  
      // 初始位置居中（仅设置 X，Y 固定在预览线）
      const p = this.preview.position;
      this.preview.active = true;
      this.preview.setPosition(v3(0, this.previewY, p.z));
    }
  
    onMove(e: EventTouch) {
      if (this.isGameOver) return;
      const loc = e.getUILocation();
      // 将屏幕坐标转本地 Canvas 坐标（父节点是 Canvas）
      const ui = this.node.getComponent(UITransform)!;
      const local = ui.convertToNodeSpaceAR(new Vec3(loc.x, loc.y, 0));
  
      // 约束 X
      const halfW = ui.contentSize.width / 2;
      const padding = this.previewClampPadding;
      const x = math.clamp(local.x, -halfW + padding, halfW - padding);
  
      const p = this.preview.position;
      this.preview.setPosition(v3(x, this.previewY, p.z));
    }
  
    onDrop() {
      if (this.isGameOver || !this.canDrop) return;
      this.canDrop = false;
  
      const dropPos = this.preview.worldPosition;
      this.spawnFruit(this.nextLevel, dropPos);
  
      // 队列前移 & 随机新队列
      this.nextLevel = this.queuedLevel;
      this.queuedLevel = randomStartLevel(1, this.randomStartMaxLevel);
      this.refreshPreview();
  
      // 冷却
      this.scheduleOnce(() => (this.canDrop = true), this.spawnCooldown);
    }
  
    spawnFruit(level: number, worldPos: Vec3, inheritVel?: Vec2) {
      const node = this.pool.size() > 0 ? this.pool.get()! : instantiate(this.fruitPrefab);
      node.parent = this.fruitRoot;
      node.active = true;
  
      // 转换到 FruitRoot 的本地坐标
      const local = this.fruitRoot.getComponent(UITransform)!.convertToNodeSpaceAR(worldPos.clone());
      node.setPosition(local);
      node.setScale(1, 1, 1);
      node.setRotationFromEuler(0, 0, 0);
  
      const fruit = node.getComponent(Fruit)!;
      const index = Math.max(0, Math.min(level - 1, FRUITS.length - 1));
      const sf = FRUITS[index].sprite!;
      fruit.init(level, sf, this);
  
      // 让它有一点随机水平初速度，手感更“弹”
      const rb = node.getComponent(RigidBody2D)!;
      const vx = Math.random() * 200 - 100;
      rb.linearVelocity = inheritVel || new Vec2(vx, 0);
  
      // 轻微缩放弹出效果
      node.setScale(0.9, 0.9, 1);
      tween(node).to(0.1, { scale: v3(1, 1, 1) }).start();
  
      // 可选音效：下落
      // this.playSfx(0.1);
  
      return fruit;
    }
  
    // 被 Fruit 调用：把两颗同级水果合成到 nextLevel
    spawnMerged(nextLevel: number, worldMid: Vec3, a: Fruit, b: Fruit) {
      if (this.isGameOver) return;
  
      // 读两者速度，合成后给一个小的向上速度，避免“坍塌”
      const va = a.getComponent(RigidBody2D)!.linearVelocity;
      const vb = b.getComponent(RigidBody2D)!.linearVelocity;
      const inherit = new Vec2((va.x + vb.x) * 0.25, Math.max(120, (va.y + vb.y) * 0.25));
  
      // 回收/删除旧的
      this.recycleFruit(a.node);
      this.recycleFruit(b.node);
  
      // 生成新的
      const f = this.spawnFruit(clampLevel(nextLevel), worldMid, inherit);
  
      // 计分：按目标等级给分
      this.updateScore(this.score + FRUITS[clampLevel(nextLevel) - 1].score);
  
      // 合成特效：放大闪烁
      const n = f.node;
      const s0 = n.scale.clone();
      tween(n)
        .to(0.06, { scale: v3(s0.x * 1.15, s0.y * 1.15, 1) })
        .to(0.08, { scale: v3(1, 1, 1) })
        .start();
  
      // 音效：合成
      this.playSfx(0.2);
    }
  
    recycleFruit(node: Node) {
      const fr = node.getComponent(Fruit);
      if (fr) fr.removed = true;
      node.removeFromParent();
      this.pool.put(node);
    }
  
    updateScore(v: number) {
      this.score = v;
      if (this.scoreLabel) this.scoreLabel.string = `${this.score}`;
      if (this.score > this.best) {
        this.best = this.score;
        sys.localStorage.setItem('best', String(this.best));
      }
      if (this.bestLabel) this.bestLabel.string = `${this.best}`;
    }
  
    setDanger(on: boolean) {
      this.dangerOn = on;
      if (this.dropLine) this.dropLine.active = on;
    }
  
    onGameOver() {
      if (this.isGameOver) return;
      this.isGameOver = true;
      this.canDrop = false;
      this.setDanger(true);
  
      // 所有水果轻微变暗/缩放（可选）
      this.fruitRoot.children.forEach((n) =>
        tween(n).to(0.2, { scale: v3(0.95, 0.95, 1) }).start()
      );
  
      // 失败音
      this.playSfx(0.35);
    }
  
    restart() {
      this.reset();
      this.canDrop = true;
    }
  
    playSfx(vol = 0.2) {
      if (!this.sfx || !this.sfx.clip) return;
      try {
        this.sfx.volume = vol;
        this.sfx.playOneShot(this.sfx.clip, vol);
      } catch {}
    }
  }
  