const MOON_GARDEN_INPUTS = {
  light: {
    label: "Light",
    short: "L",
    color: 0xfff08a,
    description: "warm sun lamp",
  },
  water: {
    label: "Water",
    short: "W",
    color: 0x74d7ff,
    description: "tiny ice drops",
  },
  crystal: {
    label: "Crystal",
    short: "C",
    color: 0xcfa6ff,
    description: "singing crystal",
  },
};

const MOON_GARDEN_PLANTS = [
  {
    id: "sprout",
    name: "Glow Sprout",
    alien: "Mira",
    rule: "Light wakes the leaf before water can move.",
    recipe: ["light", "water", "crystal"],
    bloomColor: 0x95ffbf,
    accentColor: 0xfff08a,
    reward: "A bright sprout opens and shares oxygen bubbles.",
  },
  {
    id: "bell",
    name: "Moon Bell",
    alien: "Tavo",
    rule: "Water carries the signal before crystals ring.",
    recipe: ["water", "crystal", "light"],
    bloomColor: 0x8eeaff,
    accentColor: 0xcfa6ff,
    reward: "The bell flower hums a soft pattern across the garden.",
  },
  {
    id: "starvine",
    name: "Star Vine",
    alien: "Nori",
    rule: "Crystals point the vine, then light and water help it climb.",
    recipe: ["crystal", "light", "water"],
    bloomColor: 0xfbd36d,
    accentColor: 0x74d7ff,
    reward: "The vine curls into a tiny constellation path.",
  },
];

function moonGardenRecipeText(recipe) {
  return recipe.map((key) => MOON_GARDEN_INPUTS[key].label).join(" / ");
}

function createMoonGardenRescueGame(mount, callbacks = {}) {
  const PhaserLib = window.Phaser;
  if (!PhaserLib) return null;

  class MoonGardenScene extends PhaserLib.Scene {
    constructor() {
      super("MoonGardenScene");
      this.selectedPlantIndex = 0;
      this.sequence = [];
      this.completed = new Set();
      this.phase = "choose";
      this.totalMistakes = 0;
      this.currentPlantMistakes = 0;
      this.perfectBlooms = 0;
    }

    preload() {
      this.load.image(
        "moon-garden-aliens",
        "data/generated-assets/moon-aliens/aliens.png",
      );
      const seen = new Set();
      this.load.on("loaderror", (file) => {
        const key = file && file.key;
        if (!key || seen.has(key)) return;
        seen.add(key);
        if (typeof reportSpaceError === "function") {
          reportSpaceError("Phaser image failed to load.", {
            source: "MoonGardenScene",
            asset: file && file.src ? file.src : key,
          });
        }
      });
    }

    create() {
      const { width, height } = this.scale;
      this.cameras.main.setBackgroundColor("#06101c");
      this.drawSky(width, height);
      this.drawLunarGround(width, height);
      this.createAliens(width, height);
      this.createGardenBeds(width, height);
      this.createInputPads(width, height);
      this.createRecipeGuide(width, height);
      this.createSceneText(width, height);
      this.input.keyboard?.on("keydown-L", () => this.applyInput("light"));
      this.input.keyboard?.on("keydown-W", () => this.applyInput("water"));
      this.input.keyboard?.on("keydown-C", () => this.applyInput("crystal"));
      this.scale.on("resize", this.relayout, this);
      this.events.once("shutdown", () =>
        this.scale.off("resize", this.relayout, this),
      );
      this.selectPlant(0);
      callbacks.onRound?.(this.currentPlant());
    }

    relayout() {
      if (!this.sys || !this.sys.isActive()) return;
      const { width, height } = this.scale;
      const compact = width < 640 || height < 700;

      if (this.statusText) {
        this.statusText.setPosition(24, compact ? 48 : 52);
        this.statusText.setStyle({
          wordWrap: {
            width: Math.min(compact ? width - 48 : 560, width - 48),
          },
        });
      }
      if (this.promptText) {
        this.promptText.setPosition(24, compact ? 108 : 100);
        this.promptText.setStyle({
          wordWrap: {
            width: Math.min(compact ? width - 48 : 610, width - 48),
          },
        });
      }
      if (this.sequenceText) this.sequenceText.setPosition(width - 24, 24);

      if (this.alienGroup) {
        const alienY = compact ? height * 0.47 : height * 0.49;
        this.alienGroup.setPosition(width * 0.5, alienY);
        this.alienGroup.setDisplaySize(
          Math.min(compact ? 250 : 380, width * 0.46),
          Math.min(compact ? 170 : 250, height * 0.28),
        );
      }

      if (this.plantViews && this.plantViews.length) {
        const bedY = compact ? height * 0.6 : height * 0.68;
        const spacing = Math.min(compact ? 118 : 190, width * 0.28);
        const startX = width * 0.5 - spacing;
        this.plantViews.forEach((view, index) => {
          view.root.setPosition(startX + index * spacing, bedY);
        });
      }

      if (this.pads && this.pads.length === 3) {
        const padY = compact
          ? Math.min(height * 0.74, height - 170)
          : Math.min(height - 104, height * 0.82);
        const gap = compact ? 96 : 138;
        const xs = [width * 0.5 - gap, width * 0.5, width * 0.5 + gap];
        this.pads.forEach((pad, i) => pad.setPosition(xs[i], padY));
      }

      if (this.recipeMarkers && this.recipeMarkers.length) {
        const y = compact ? height * 0.2 : height * 0.18;
        this.recipeMarkers.forEach((entry, i) => {
          entry.marker.setPosition(width * 0.5 - 72 + i * 72, y);
        });
      }

      if (typeof this.updatePadHints === "function") this.updatePadHints();
    }

    drawSky(width, height) {
      const stars = this.add.graphics();
      for (let i = 0; i < 150; i += 1) {
        const x = PhaserLib.Math.Between(0, width);
        const y = PhaserLib.Math.Between(0, Math.floor(height * 0.68));
        stars.fillStyle(0xffffff, PhaserLib.Math.FloatBetween(0.28, 0.85));
        stars.fillCircle(x, y, PhaserLib.Math.FloatBetween(0.7, 1.8));
      }
      const earth = this.add.graphics();
      earth.fillStyle(0x6bbdff, 0.92);
      earth.fillCircle(
        width - (width < 620 ? 50 : 86),
        width < 620 ? 118 : 86,
        width < 620 ? 22 : 34,
      );
      earth.fillStyle(0x77e19b, 0.75);
      earth.fillEllipse(
        width - (width < 620 ? 58 : 98),
        width < 620 ? 114 : 80,
        width < 620 ? 18 : 28,
        width < 620 ? 8 : 13,
      );
      earth.fillEllipse(
        width - (width < 620 ? 42 : 74),
        width < 620 ? 126 : 96,
        width < 620 ? 14 : 22,
        width < 620 ? 7 : 11,
      );
      earth.lineStyle(2, 0xeef7ff, 0.22);
      earth.strokeCircle(
        width - (width < 620 ? 50 : 86),
        width < 620 ? 118 : 86,
        width < 620 ? 22 : 34,
      );
    }

    drawLunarGround(width, height) {
      this.ground = this.add.graphics();
      this.ground.fillStyle(0xcfd3c4, 1);
      this.ground.fillEllipse(
        width * 0.5,
        height * 0.9,
        width * 1.32,
        height * 0.42,
      );
      this.ground.fillStyle(0x8f948b, 0.28);
      this.ground.fillEllipse(
        width * 0.23,
        height * 0.84,
        width * 0.18,
        height * 0.035,
      );
      this.ground.fillEllipse(
        width * 0.58,
        height * 0.9,
        width * 0.28,
        height * 0.045,
      );
      this.ground.fillEllipse(
        width * 0.82,
        height * 0.8,
        width * 0.14,
        height * 0.028,
      );
    }

    createAliens(width, height) {
      const compact = width < 640 || height < 700;
      const alienY = compact ? height * 0.47 : height * 0.49;
      this.alienGlow = this.add.graphics();
      this.alienGlow.fillStyle(0x95ffbf, 0.14);
      this.alienGlow.fillEllipse(
        width * 0.5,
        alienY + 4,
        compact ? 190 : 260,
        compact ? 98 : 136,
      );
      this.alienGroup = this.add.image(
        width * 0.5,
        alienY,
        "moon-garden-aliens",
      );
      this.alienGroup.setDisplaySize(
        Math.min(compact ? 250 : 380, width * 0.46),
        Math.min(compact ? 170 : 250, height * 0.28),
      );
      this.tweens.add({
        targets: this.alienGroup,
        y: alienY - 8,
        duration: 1300,
        yoyo: true,
        repeat: -1,
        ease: "Sine.inOut",
      });
    }

    createGardenBeds(width, height) {
      this.plantViews = [];
      const compact = width < 640;
      const bedY = compact ? height * 0.6 : height * 0.68;
      const spacing = Math.min(compact ? 118 : 190, width * 0.28);
      const startX = width * 0.5 - spacing;
      MOON_GARDEN_PLANTS.forEach((plant, index) => {
        const x = startX + index * spacing;
        const root = this.add.container(x, bedY);
        const bed = this.add.graphics();
        bed.fillStyle(0x3f4650, 0.95);
        bed.fillRoundedRect(-44, 26, 88, 22, 10);
        bed.fillStyle(0x252a30, 0.9);
        bed.fillEllipse(0, 27, 92, 24);
        bed.lineStyle(2, 0xeef7ff, 0.18);
        bed.strokeEllipse(0, 27, 92, 24);

        const stem = this.add.graphics();
        stem.lineStyle(5, 0x5fbf86, 1);
        stem.beginPath();
        stem.moveTo(0, 26);
        stem.lineTo(0, -2);
        stem.strokePath();
        stem.fillStyle(0x5fbf86, 1);
        stem.fillEllipse(-10, 7, 22, 10);
        stem.fillEllipse(11, -1, 22, 10);

        const bloom = this.add.graphics();
        bloom.setScale(0.18);
        bloom.setAlpha(0.18);
        this.drawBloom(bloom, plant.bloomColor, plant.accentColor);

        const halo = this.add.graphics();
        halo.fillStyle(plant.bloomColor, 0.18);
        halo.fillCircle(0, -30, 38);
        halo.setAlpha(0);

        const label = this.add
          .text(0, 60, plant.name, {
            fontFamily: "Inter, sans-serif",
            fontSize: compact ? "11px" : "13px",
            fontStyle: "800",
            color: "#f7fbff",
            align: "center",
          })
          .setOrigin(0.5);

        root.add([halo, bed, stem, bloom, label]);
        root.setSize(104, 120);
        root.setInteractive(
          new PhaserLib.Geom.Rectangle(-52, -54, 104, 132),
          PhaserLib.Geom.Rectangle.Contains,
        );
        root.on("pointerdown", () => this.selectPlant(index));
        this.plantViews.push({
          root,
          bed,
          bloom,
          halo,
          label,
          plant,
          solved: false,
        });
      });
    }

    drawBloom(target, bloomColor, accentColor) {
      target.clear();
      target.fillStyle(bloomColor, 0.98);
      for (let i = 0; i < 6; i += 1) {
        const angle = (Math.PI * 2 * i) / 6;
        target.fillEllipse(
          Math.cos(angle) * 16,
          -30 + Math.sin(angle) * 13,
          17,
          29,
        );
      }
      target.fillStyle(accentColor, 1);
      target.fillCircle(0, -30, 10);
      target.lineStyle(2, 0xffffff, 0.36);
      target.strokeCircle(0, -30, 30);
    }

    createInputPads(width, height) {
      this.pads = [];
      const compact = width < 640 || height < 700;
      const padY = compact
        ? Math.min(height * 0.74, height - 170)
        : Math.min(height - 104, height * 0.82);
      const padW = compact ? 86 : 118;
      const gap = compact ? 96 : 138;
      const entries = [
        ["light", width * 0.5 - gap],
        ["water", width * 0.5],
        ["crystal", width * 0.5 + gap],
      ];
      entries.forEach(([key, x]) => {
        const info = MOON_GARDEN_INPUTS[key];
        const pad = this.add.container(x, padY);
        const bg = this.add.graphics();
        bg.fillStyle(info.color, 0.2);
        bg.fillRoundedRect(-padW / 2, -27, padW, 54, 16);
        bg.lineStyle(2, info.color, 0.82);
        bg.strokeRoundedRect(-padW / 2, -27, padW, 54, 16);
        const short = this.add
          .text(0, -4, info.short, {
            fontFamily: "Inter, sans-serif",
            fontSize: compact ? "20px" : "24px",
            fontStyle: "900",
            color: "#f7fbff",
          })
          .setOrigin(0.5);
        const label = this.add
          .text(0, 17, info.label, {
            fontFamily: "Inter, sans-serif",
            fontSize: compact ? "10px" : "12px",
            fontStyle: "800",
            color: "#dcecff",
          })
          .setOrigin(0.5);
        pad.add([bg, short, label]);
        pad.setSize(padW, 64);
        pad.signalKey = key;
        pad.padWidth = padW;
        pad.padBg = bg;
        pad.setInteractive({ useHandCursor: true });
        pad.on("pointerdown", () => this.applyInput(key));
        this.pads.push(pad);
      });
      this.nextPadGlow = this.add.graphics();
    }

    createRecipeGuide(width, height) {
      this.recipeMarkers = [];
      const compact = width < 640 || height < 700;
      const y = compact ? height * 0.2 : height * 0.18;
      [0, 1, 2].forEach((index) => {
        const marker = this.add.container(width * 0.5 - 72 + index * 72, y);
        const bg = this.add.graphics();
        bg.fillStyle(0x111b2c, 0.82);
        bg.fillRoundedRect(-28, -20, 56, 40, 12);
        bg.lineStyle(1, 0xffffff, 0.18);
        bg.strokeRoundedRect(-28, -20, 56, 40, 12);
        const dot = this.add.graphics();
        dot.fillStyle(0xffffff, 0.28);
        dot.fillCircle(0, -2, 9);
        const label = this.add
          .text(0, 15, "", {
            fontFamily: "Inter, sans-serif",
            fontSize: "9px",
            fontStyle: "900",
            color: "#f7fbff",
          })
          .setOrigin(0.5);
        marker.add([bg, dot, label]);
        this.recipeMarkers.push({ marker, dot, label });
      });
    }

    createSceneText(width, height) {
      const compact = width < 640 || height < 700;
      this.titleText = this.add.text(24, 20, "Moon Garden Rescue", {
        fontFamily: "Inter, sans-serif",
        fontSize: compact ? "16px" : "18px",
        fontStyle: "900",
        color: "#95ffbf",
      });
      this.statusText = this.add.text(24, compact ? 48 : 52, "", {
        fontFamily: "Inter, sans-serif",
        fontSize: compact ? "21px" : "30px",
        fontStyle: "900",
        color: "#f7fbff",
        wordWrap: { width: Math.min(compact ? width - 48 : 560, width - 48) },
      });
      this.promptText = this.add.text(24, compact ? 108 : 100, "", {
        fontFamily: "Inter, sans-serif",
        fontSize: compact ? "13px" : "16px",
        color: "#dcecff",
        wordWrap: { width: Math.min(compact ? width - 48 : 610, width - 48) },
      });
      this.sequenceText = this.add
        .text(width - 24, 24, "", {
          fontFamily: "Inter, sans-serif",
          fontSize: compact ? "13px" : "16px",
          fontStyle: "900",
          color: "#fff08a",
        })
        .setOrigin(1, 0);
    }

    currentPlant() {
      return MOON_GARDEN_PLANTS[this.selectedPlantIndex];
    }

    selectPlant(index, options = {}) {
      if (this.phase === "blooming" && !options.force) return;
      this.selectedPlantIndex = index;
      this.phase = this.completed.has(this.currentPlant().id)
        ? "review"
        : "play";
      this.sequence = [];
      this.currentPlantMistakes = 0;
      const plant = this.currentPlant();
      this.plantViews.forEach((view, viewIndex) => {
        const selected = viewIndex === index;
        view.root.setScale(selected ? 1.08 : 1);
        view.label.setColor(selected ? "#fff08a" : "#f7fbff");
      });
      this.updateRecipeGuide(plant);
      this.updatePadHints();
      this.statusText.setText(`${plant.alien} teaches ${plant.name}`);
      this.promptText.setText(
        this.completed.has(plant.id)
          ? `${plant.name} is already glowing. Choose another plant to keep rescuing.`
          : `${plant.rule} Recipe: ${moonGardenRecipeText(plant.recipe)}.`,
      );
      this.sequenceText.setText(
        this.completed.has(plant.id) ? "Bloomed" : "Mix: --",
      );
      callbacks.onRound?.(plant);
    }

    updateRecipeGuide(plant) {
      this.recipeMarkers.forEach((entry, index) => {
        const key = plant.recipe[index];
        const info = MOON_GARDEN_INPUTS[key];
        entry.dot.clear();
        entry.dot.fillStyle(info.color, 0.95);
        entry.dot.fillCircle(0, -2, 9);
        entry.label.setText(info.short);
        entry.marker.setAlpha(1);
      });
    }

    updatePadHints() {
      if (!this.nextPadGlow) return;
      this.nextPadGlow.clear();
      this.pads.forEach((pad) =>
        pad.setAlpha(this.phase === "play" ? 0.72 : 0.48),
      );
      if (this.phase !== "play") return;
      const plant = this.currentPlant();
      const expected = plant.recipe[this.sequence.length];
      const pad = this.pads.find((item) => item.signalKey === expected);
      if (!pad) return;
      pad.setAlpha(1);
      const info = MOON_GARDEN_INPUTS[expected];
      this.nextPadGlow.lineStyle(4, info.color, 0.95);
      this.nextPadGlow.strokeRoundedRect(
        pad.x - pad.padWidth / 2 - 5,
        pad.y - 32,
        pad.padWidth + 10,
        64,
        18,
      );
      this.nextPadGlow.fillStyle(info.color, 0.1);
      this.nextPadGlow.fillRoundedRect(
        pad.x - pad.padWidth / 2 - 5,
        pad.y - 32,
        pad.padWidth + 10,
        64,
        18,
      );
    }

    applyInput(key) {
      if (this.phase !== "play") return;
      const plant = this.currentPlant();
      const expected = plant.recipe[this.sequence.length];
      const pad = this.pads.find((item) => item.signalKey === key);
      this.pulsePad(pad, key);

      if (key !== expected) {
        this.totalMistakes += 1;
        this.currentPlantMistakes += 1;
        this.sequence = [];
        this.sequenceText.setText("Mix: reset");
        this.promptText.setText(
          `${plant.alien} points gently: ${MOON_GARDEN_INPUTS[expected].label} comes next. Try ${moonGardenRecipeText(plant.recipe)}.`,
        );
        this.recipeMarkers.forEach((entry) => entry.marker.setAlpha(1));
        this.showWrongInput(key);
        this.updatePadHints();
        this.cameras.main.shake(120, 0.005);
        callbacks.onMiss?.(plant, this.totalMistakes, expected);
        return;
      }

      this.sequence.push(key);
      this.sequenceText.setText(
        `Mix: ${this.sequence.map((item) => MOON_GARDEN_INPUTS[item].short).join(" / ")}`,
      );
      const marker = this.recipeMarkers[this.sequence.length - 1];
      if (marker) marker.marker.setAlpha(0.34);
      this.sendEnergyToPlant(key);
      this.updatePadHints();
      if (this.sequence.length === plant.recipe.length) {
        this.completePlant(plant);
      }
    }

    pulsePad(pad, key) {
      if (!pad) return;
      const color = MOON_GARDEN_INPUTS[key].color;
      const glow = this.add.graphics();
      glow.fillStyle(color, 0.32);
      glow.fillCircle(pad.x, pad.y, 42);
      this.tweens.add({
        targets: glow,
        alpha: 0,
        scale: 2,
        duration: 420,
        onComplete: () => glow.destroy(),
      });
      this.tweens.add({ targets: pad, scale: 1.08, yoyo: true, duration: 110 });
    }

    showWrongInput(key) {
      const pad = this.pads.find((item) => item.signalKey === key);
      if (!pad) return;
      const ring = this.add.graphics();
      ring.lineStyle(4, 0xff6b7c, 0.95);
      ring.strokeCircle(pad.x, pad.y, 36);
      this.tweens.add({
        targets: ring,
        alpha: 0,
        scale: 1.7,
        duration: 360,
        onComplete: () => ring.destroy(),
      });
    }

    sendEnergyToPlant(key) {
      const view = this.plantViews[this.selectedPlantIndex];
      const pad = this.pads.find((item) => item.signalKey === key);
      if (!view || !pad) return;
      const particle = this.add.graphics();
      particle.fillStyle(MOON_GARDEN_INPUTS[key].color, 1);
      particle.fillCircle(0, 0, 8);
      particle.setPosition(pad.x, pad.y - 16);
      this.tweens.add({
        targets: particle,
        x: view.root.x,
        y: view.root.y - 28,
        duration: 360,
        ease: "Sine.out",
        onComplete: () => particle.destroy(),
      });
    }

    completePlant(plant) {
      this.phase = "blooming";
      this.completed.add(plant.id);
      const view = this.plantViews[this.selectedPlantIndex];
      view.solved = true;
      if (this.currentPlantMistakes === 0) {
        this.perfectBlooms += 1;
      }
      this.statusText.setText(`${plant.name} blooms`);
      this.promptText.setText(
        this.currentPlantMistakes === 0
          ? `${plant.reward} Perfect recipe.`
          : `${plant.reward} It needed ${this.currentPlantMistakes + 1} tries.`,
      );
      this.sequenceText.setText(
        `${this.completed.size}/${MOON_GARDEN_PLANTS.length} restored`,
      );
      if (this.nextPadGlow) this.nextPadGlow.clear();
      this.pads.forEach((pad) => pad.setAlpha(0.72));
      callbacks.onSolved?.(
        plant,
        this.completed.size,
        this.currentPlantMistakes,
      );
      this.bloomPlant(view, plant);
      this.time.delayedCall(1250, () => {
        if (!this.sys || !this.sys.isActive()) return;
        if (this.completed.size >= MOON_GARDEN_PLANTS.length) {
          this.phase = "complete";
          const careGrade =
            this.totalMistakes === 0
              ? "Perfect garden care"
              : this.totalMistakes <= 2
                ? "Careful garden care"
                : "Garden restored";
          this.statusText.setText("Garden restored");
          this.promptText.setText(
            `${careGrade}: every moon plant is glowing with ${this.perfectBlooms} perfect blooms.`,
          );
          this.sequenceText.setText(`${this.totalMistakes} resets`);
          callbacks.onComplete?.({
            totalMistakes: this.totalMistakes,
            perfectBlooms: this.perfectBlooms,
            careGrade,
          });
          return;
        }
        const nextIndex = MOON_GARDEN_PLANTS.findIndex(
          (item) => !this.completed.has(item.id),
        );
        this.selectPlant(nextIndex, { force: true });
      });
    }

    bloomPlant(view, plant) {
      view.halo.setAlpha(1);
      this.tweens.add({
        targets: view.bloom,
        scale: 1,
        alpha: 1,
        duration: 520,
        ease: "Back.out",
      });
      this.tweens.add({
        targets: view.halo,
        scale: 1.55,
        alpha: 0.4,
        duration: 760,
        yoyo: true,
        repeat: 1,
      });
      for (let i = 0; i < 18; i += 1) {
        const sparkle = this.add.graphics();
        sparkle.fillStyle(i % 2 ? plant.bloomColor : plant.accentColor, 1);
        sparkle.fillCircle(0, 0, PhaserLib.Math.Between(2, 4));
        sparkle.setPosition(view.root.x, view.root.y - 30);
        const angle = PhaserLib.Math.FloatBetween(0, Math.PI * 2);
        const distance = PhaserLib.Math.Between(28, 82);
        this.tweens.add({
          targets: sparkle,
          x: view.root.x + Math.cos(angle) * distance,
          y: view.root.y - 30 + Math.sin(angle) * distance,
          alpha: 0,
          duration: 680,
          ease: "Sine.out",
          onComplete: () => sparkle.destroy(),
        });
      }
    }
  }

  return new PhaserLib.Game({
    type: PhaserLib.AUTO,
    parent: mount,
    width: mount.clientWidth || 960,
    height: mount.clientHeight || 620,
    backgroundColor: "#06101c",
    scale: {
      mode: PhaserLib.Scale.RESIZE,
      autoCenter: PhaserLib.Scale.CENTER_BOTH,
    },
    scene: MoonGardenScene,
  });
}

function MoonGardenRescuePhaserLevel({ onExit }) {
  const gameRef = useRef(null);
  const mountRef = useRef(null);
  const [runKey, setRunKey] = useState(0);
  const [status, setStatus] = useState("Choose a moon plant, then mix light, water, and crystal in order.");
  const [solved, setSolved] = useState(0);
  const [complete, setComplete] = useState(false);

  useEffect(() => {
    if (!mountRef.current) return undefined;
    if (!window.Phaser) {
      setStatus(
        "Phaser did not load. Check the network and refresh this level.",
      );
      return undefined;
    }
    gameRef.current = createMoonGardenRescueGame(mountRef.current, {
      onRound: (plant) => {
        setComplete(false);
        setStatus(
          `${plant.alien}: ${plant.rule} Tap ${moonGardenRecipeText(plant.recipe)}.`,
        );
      },
      onMiss: (plant, totalMistakes, expected) => {
        setStatus(
          `${plant.alien} helps you reset. ${MOON_GARDEN_INPUTS[expected].label} comes next. Resets: ${totalMistakes}.`,
        );
        playKidSound("boop");
      },
      onSolved: (plant, count, plantMistakes) => {
        setSolved(count);
        setStatus(
          plantMistakes === 0
            ? `${plant.reward} Perfect recipe.`
            : plant.reward,
        );
        playKidSound("chime");
      },
      onComplete: (result) => {
        setComplete(true);
        setStatus(
          `${result.careGrade}. ${result.perfectBlooms}/${MOON_GARDEN_PLANTS.length} perfect blooms; ${result.totalMistakes} resets.`,
        );
        playKidSound("whoosh");
      },
    });
    return () => {
      if (gameRef.current) {
        gameRef.current.destroy(true);
        gameRef.current = null;
      }
      if (window.__narration) window.__narration.stop();
    };
  }, [runKey]);

  const restart = () => {
    setStatus("Choose a moon plant, then mix light, water, and crystal in order.");
    setSolved(0);
    setComplete(false);
    setRunKey((key) => key + 1);
  };

  return (
    <section className="moon-garden-level" aria-label="Moon Garden Rescue Phaser game">
      <button className="planet-sort-back" onClick={onExit}>
        Back to planets
      </button>
      <div className="moon-garden-frame">
        <div ref={mountRef} className="moon-garden-game" />
        <div className="moon-garden-hud">
          <span>Phaser Moon Garden</span>
          <strong>{status}</strong>
          <div className="moon-garden-progress" aria-label="Moon plants restored">
            {MOON_GARDEN_PLANTS.map((plant, index) => (
              <i key={plant.id} className={index < solved ? "on" : ""} />
            ))}
          </div>
          {complete ? (
            <button className="moon-garden-replay" onClick={restart}>
              Replay
            </button>
          ) : null}
        </div>
      </div>
    </section>
  );
}
