// zephy-buddy.jsx
// Small global guide overlay used by game screens.

const ZEPHY_SPRITE_SHEETS = {
  core: "data/sprites/zephy-space-pup-sheet-padded.png",
  celebrate: "data/sprites/zephy-celebration-sheet-padded.png",
  hint: "data/sprites/zephy-hints-sheet-padded.png",
  tryAgain: "data/sprites/zephy-try-again-sheet-padded.png",
};

const ZEPHY_FRAMES = {
  idle: { sheet: "core", x: 0, y: 0 },
  wave: { sheet: "core", x: 1, y: 0 },
  cheer: { sheet: "core", x: 2, y: 0 },
  hint: { sheet: "core", x: 3, y: 0 },
  danceLeft: { sheet: "core", x: 0, y: 1 },
  danceRight: { sheet: "core", x: 1, y: 1 },
  jump: { sheet: "core", x: 2, y: 1 },
  spin: { sheet: "core", x: 3, y: 1 },
  sparkle: { sheet: "core", x: 0, y: 2 },
  pawUp: { sheet: "core", x: 1, y: 2 },
  tryAgain: { sheet: "core", x: 2, y: 2 },
  calm: { sheet: "core", x: 3, y: 2 },
  celebrationCheer: { sheet: "celebrate", x: 0, y: 0 },
  confettiHop: { sheet: "celebrate", x: 1, y: 0 },
  victoryLeft: { sheet: "celebrate", x: 2, y: 0 },
  victoryRight: { sheet: "celebrate", x: 3, y: 0 },
  spinDance: { sheet: "celebrate", x: 0, y: 1 },
  backflip: { sheet: "celebrate", x: 1, y: 1 },
  proudSalute: { sheet: "celebrate", x: 2, y: 1 },
  tailWag: { sheet: "celebrate", x: 3, y: 1 },
  helmetWow: { sheet: "celebrate", x: 0, y: 2 },
  moonwalk: { sheet: "celebrate", x: 1, y: 2 },
  happyClap: { sheet: "celebrate", x: 2, y: 2 },
  heroPose: { sheet: "celebrate", x: 3, y: 2 },
  headTilt: { sheet: "hint", x: 0, y: 0 },
  pointLeft: { sheet: "hint", x: 1, y: 0 },
  pointRight: { sheet: "hint", x: 2, y: 0 },
  telescope: { sheet: "hint", x: 3, y: 0 },
  starMap: { sheet: "hint", x: 0, y: 1 },
  thinking: { sheet: "hint", x: 1, y: 1 },
  softNod: { sheet: "hint", x: 2, y: 1 },
  listening: { sheet: "hint", x: 3, y: 1 },
  compass: { sheet: "hint", x: 0, y: 2 },
  arrowSpark: { sheet: "hint", x: 1, y: 2 },
  slowDown: { sheet: "hint", x: 2, y: 2 },
  hintPawUp: { sheet: "hint", x: 3, y: 2 },
  softTryAgain: { sheet: "tryAgain", x: 0, y: 0 },
  offeringPaw: { sheet: "tryAgain", x: 1, y: 0 },
  braveJump: { sheet: "tryAgain", x: 2, y: 0 },
  dustOff: { sheet: "tryAgain", x: 3, y: 0 },
  hugGesture: { sheet: "tryAgain", x: 0, y: 1 },
  deepBreath: { sheet: "tryAgain", x: 1, y: 1 },
  oopsWobble: { sheet: "tryAgain", x: 2, y: 1 },
  wink: { sheet: "tryAgain", x: 3, y: 1 },
  starShield: { sheet: "tryAgain", x: 0, y: 2 },
  sleepyFloat: { sheet: "tryAgain", x: 1, y: 2 },
  readyStance: { sheet: "tryAgain", x: 2, y: 2 },
  proudNod: { sheet: "tryAgain", x: 3, y: 2 },
};

const ZEPHY_POSE_PACKS = {
  start: ["wave", "headTilt", "happyClap", "offeringPaw"],
  hint: [
    "hint",
    "headTilt",
    "pointLeft",
    "pointRight",
    "telescope",
    "starMap",
    "thinking",
    "softNod",
    "listening",
    "compass",
    "arrowSpark",
    "slowDown",
    "hintPawUp",
  ],
  celebrate: [
    "cheer",
    "sparkle",
    "celebrationCheer",
    "confettiHop",
    "victoryLeft",
    "victoryRight",
    "spinDance",
    "backflip",
    "proudSalute",
    "tailWag",
    "helmetWow",
    "moonwalk",
    "happyClap",
    "heroPose",
  ],
  tryAgain: [
    "tryAgain",
    "softTryAgain",
    "offeringPaw",
    "braveJump",
    "dustOff",
    "hugGesture",
    "deepBreath",
    "oopsWobble",
    "wink",
    "starShield",
    "readyStance",
    "proudNod",
  ],
};

const ZEPHY_GAME_LINES = {
  maze: {
    start: "I am right here, captain. Let us find those planets together.",
    hints: [
      "Tiny turns are brave turns.",
      "Look for the open path, then scoot with me.",
      "You are steering like a real captain!",
    ],
  },
  moonRover: {
    start: "Rover paws ready. Let us collect moon rocks.",
    hints: [
      "Slow wheels can still make big discoveries.",
      "Try the guide button if the rover feels lost.",
      "That was a super brave jump!",
    ],
  },
  marsRover: {
    start: "Mars buddy mode on. I will sniff out science clues with you.",
    hints: [
      "Follow the bright path one little drive at a time.",
      "Every sample tells Mars's story.",
      "You are exploring like a rover engineer!",
    ],
  },
  pilot: {
    start: "Space Pup co-pilot checking in.",
    hints: [
      "Small taps make smooth flying.",
      "Breathe, steer, and try again with me.",
      "You are docking like a careful captain!",
    ],
  },
  blackHole: {
    start: "I will stay close while we peek at the black hole.",
    hints: [
      "Stay curious and keep a little distance.",
      "Bright rings show where gravity is doing big work.",
      "Super brave flying, captain.",
    ],
  },
  treasure: {
    start: "Treasure stop! Let us collect clues for the star chart.",
    hints: [
      "Look carefully, then tap one shiny clue.",
      "Every treasure helps us remember this world.",
      "You found a map piece for our adventure.",
    ],
  },
  planetSort: {
    start: "Sorting stop! Put each world where the map can find it.",
    hints: [
      "Compare one planet clue at a time.",
      "Big, small, hot, cold. The map is learning.",
      "Nice sorting, captain.",
    ],
  },
  engineMatch: {
    start: "Engine stop! Match the parts so our ship can keep exploring.",
    hints: [
      "Find the part that makes the ship feel ready.",
      "One good match powers the next route.",
      "The engine sounds proud of you.",
    ],
  },
  rocketCause: {
    start: "Rocket lab stop! Pick what helps a rocket blast off.",
    hints: [
      "Look for the cause, then watch what happens.",
      "Rockets need a strong reason to zoom.",
      "You are thinking like a space builder.",
    ],
  },
  ufoBuilder: {
    start: "Maker stop! Build a friendly ship for the star chart.",
    hints: [
      "Choose one part and make it yours.",
      "A good ship has a job and a story.",
      "That design belongs in our map.",
    ],
  },
  mashupMaker: {
    start: "Imagination stop! Mix pieces into a brand-new space idea.",
    hints: [
      "Try two pieces that feel funny together.",
      "New worlds can start with one silly choice.",
      "That mashup makes our adventure bigger.",
    ],
  },
  connectionQuest: {
    start: "Connection stop! Link the clues that belong together.",
    hints: [
      "Find what matches, then make the path glow.",
      "Connections help the map remember.",
      "You spotted the space link.",
    ],
  },
  asteroidDodge: {
    start: "Asteroid stop! Steer gently through the busy space lane.",
    hints: [
      "Small moves keep the path smooth.",
      "Watch the next rock, not every rock.",
      "You kept our route safe.",
    ],
  },
  missionControl: {
    start: "Mission Control stop! Help the team choose the next move.",
    hints: [
      "Check one signal before you launch.",
      "Good captains pause and plan.",
      "The crew heard your smart choice.",
    ],
  },
  gravityJump: {
    start: "Gravity stop! Try a jump and feel how each world pulls.",
    hints: [
      "Pick one world, then tap Jump.",
      "Different gravity makes different hops.",
      "You felt the pull like a scientist.",
    ],
  },
  alienLanguage: {
    start: "Message stop! Decode a friendly space hello.",
    hints: [
      "Look for the symbol that matches the idea.",
      "A message is another kind of map.",
      "The aliens know you are listening.",
    ],
  },
  babyRockets: {
    start: "Baby rocket stop! Help the little rockets get ready.",
    hints: [
      "Pick one rocket that needs care.",
      "Gentle helpers make brave launches.",
      "That rocket is smiling in space.",
    ],
  },
  moonAliens: {
    start: "Moon friend stop! Help the aliens find a happy path.",
    hints: [
      "Move slowly and watch your friend.",
      "Teamwork makes the moon feel cozy.",
      "You helped a new friend.",
    ],
  },
  moonGarden: {
    start: "Moon garden stop! Help the tiny plants grow in space.",
    hints: [
      "Choose one helpful move for the garden.",
      "Plants need care, even on the Moon.",
      "The garden added green to our map.",
    ],
  },
  meteorShield: {
    start: "Shield stop! Protect the route from speedy meteors.",
    hints: [
      "Hold steady and guard one space lane.",
      "A shield can make brave explorers feel safe.",
      "The route is clear again.",
    ],
  },
  petFeeder: {
    start: "Pet stop! Feed the space friends and learn what they like.",
    hints: [
      "Watch the friend, then choose a snack.",
      "Caring is part of exploring.",
      "That space pet trusts you.",
    ],
  },
  shootingStar: {
    start: "Shooting star stop! Ride the glow and trace a bright route.",
    hints: [
      "Follow the sparkle path with small moves.",
      "A streak of light can mark the map.",
      "You rode that star so smoothly.",
    ],
  },
  marsSuitcase: {
    start: "Packing stop! Choose what an explorer needs for Mars.",
    hints: [
      "Pick one useful thing for the trip.",
      "Packing is planning for a new world.",
      "That belongs in our Mars kit.",
    ],
  },
  marsCity: {
    start: "Mars city stop! Build a place explorers can remember.",
    hints: [
      "Place one helpful thing for the city.",
      "A good city needs care and curiosity.",
      "Mars has a new map mark.",
    ],
  },
  legoRoverGarage: {
    start: "Garage stop! Build a rover that can roll into the unknown.",
    hints: [
      "Choose one sturdy rover piece.",
      "A rover needs a job before it drives.",
      "That rover is ready for the route.",
    ],
  },
  spaceMemory: {
    start: "Memory stop! Match cards to save pictures for our map.",
    hints: [
      "Turn one card, then remember where it sleeps.",
      "Memory makes the star chart stronger.",
      "You saved that clue.",
    ],
  },
  rocketPack: {
    start: "Rocket pack stop! Build the gear for our next hop.",
    hints: [
      "Choose one part and see where it fits.",
      "Good gear helps explorers travel.",
      "That pack is ready to zoom.",
    ],
  },
  helmetLab: {
    start: "Helmet stop! Make your explorer ready for the next world.",
    hints: [
      "Pick a sticker that feels like your mission.",
      "A helmet keeps the adventure safe.",
      "That explorer looks ready.",
    ],
  },
  spaceReading: {
    start: "Reading stop! Find one space idea for the star chart.",
    hints: [
      "Read one page and point to a clue.",
      "Stories help us remember worlds.",
      "That idea belongs on our map.",
    ],
  },
  storybook: {
    start: "Story stop! Turn the page and listen for a space clue.",
    hints: [
      "One page at a time is perfect.",
      "Stories make the adventure feel close.",
      "You found a story clue.",
    ],
  },
  storyShelf: {
    start: "Story shelf stop! Pick a book for our explorer path.",
    hints: [
      "Choose the story that feels ready.",
      "Books can be mission stops too.",
      "I will listen with you.",
    ],
  },
  home: {
    start: "Zephy is on the hub. Pick a mission and I will fly with you.",
    hints: [
      "Try the Mission Map. I will keep track of your badge trail.",
      "Study, play, remember. That is our space path.",
      "Your next mission is waiting, captain.",
    ],
  },
  default: {
    start: "Zephy is here. Let us make this a space adventure.",
    hints: [
      "Try one small move, then I will cheer with you.",
      "You are doing it. I am right here.",
      "Want to try again with me?",
    ],
  },
};

const ZEPHY_LINE_CLIPS = {
  "I am right here, captain. Let us find those planets together.":
    "zephy_maze_start.mp3",
  "Tiny turns are brave turns.": "zephy_tiny_turns.mp3",
  "Look for the open path, then scoot with me.": "zephy_open_path.mp3",
  "You are steering like a real captain!": "zephy_real_captain.mp3",
  "Rover paws ready. Let us collect moon rocks.": "zephy_rover_start.mp3",
  "Slow wheels can still make big discoveries.": "zephy_slow_wheels.mp3",
  "Try the guide button if the rover feels lost.": "zephy_rover_guide.mp3",
  "That was a super brave jump!": "zephy_brave_jump.mp3",
  "Mars buddy mode on. I will sniff out science clues with you.":
    "zephy_mars_start.mp3",
  "Follow the bright path one little drive at a time.":
    "zephy_bright_path.mp3",
  "Every sample tells Mars's story.": "zephy_mars_story.mp3",
  "You are exploring like a rover engineer!": "zephy_rover_engineer.mp3",
  "Space Pup co-pilot checking in.": "zephy_pilot_start.mp3",
  "Small taps make smooth flying.": "zephy_smooth_flying.mp3",
  "Breathe, steer, and try again with me.": "zephy_breathe_try_again.mp3",
  "You are docking like a careful captain!": "zephy_docking_captain.mp3",
  "I will stay close while we peek at the black hole.":
    "zephy_blackhole_start.mp3",
  "Stay curious and keep a little distance.": "zephy_blackhole_distance.mp3",
  "Bright rings show where gravity is doing big work.":
    "zephy_gravity_work.mp3",
  "Super brave flying, captain.": "zephy_brave_flying.mp3",
  "Zephy is here. Let us make this a space adventure.":
    "zephy_default_start.mp3",
  "Try one small move, then I will cheer with you.":
    "zephy_one_small_move.mp3",
  "You are doing it. I am right here.": "zephy_right_here.mp3",
  "Want to try again with me?": "zephy_try_again_with_me.mp3",
  "Yay! You did it!": "zephy_you_did_it.mp3",
  "You did it!": "zephy_you_did_it.mp3",
  "That was super brave. Want to try again with me?":
    "zephy_super_brave_try_again.mp3",
};

function zephyFrameStyle(frameName) {
  const frame = ZEPHY_FRAMES[frameName] || ZEPHY_FRAMES.idle;
  const x = frame.x * 33.3333;
  const y = frame.y * 50;
  const sheet = ZEPHY_SPRITE_SHEETS[frame.sheet] || ZEPHY_SPRITE_SHEETS.core;
  return {
    backgroundImage: `url("${sheet}")`,
    backgroundPosition: `${x}% ${y}%`,
  };
}

function zephySpeechEnabled() {
  try {
    return window.__narration ? window.__narration.isEnabled() : true;
  } catch (_) {
    return true;
  }
}

function speakZephyLine(text) {
  if (!text || !zephySpeechEnabled()) return;
  const clip = ZEPHY_LINE_CLIPS[String(text).trim()];
  if (clip) {
    try {
      if (!window.__zephyAudio) {
        window.__zephyAudio = new Audio();
        window.__zephyAudio.volume = 0.72;
      }
      window.__zephyAudio.pause();
      window.__zephyAudio.currentTime = 0;
      window.__zephyAudio.src = "data/audio/planets/" + clip;
      const playing = window.__zephyAudio.play();
      if (playing && typeof playing.catch === "function") {
        playing.catch(() => {});
      }
      return;
    } catch (_) {}
  }
  const synth = window.speechSynthesis;
  if (!synth || typeof window.SpeechSynthesisUtterance !== "function") return;
  try {
    const utterance = new window.SpeechSynthesisUtterance(text);
    utterance.lang = "en-US";
    utterance.pitch = 1.28;
    utterance.rate = 0.94;
    utterance.volume = 0.78;
    synth.cancel();
    synth.speak(utterance);
  } catch (_) {}
}

function stopZephySpeech() {
  try {
    if (window.__zephyAudio) {
      window.__zephyAudio.pause();
      window.__zephyAudio.currentTime = 0;
    }
  } catch (_) {}
  try {
    if (window.speechSynthesis) window.speechSynthesis.cancel();
  } catch (_) {}
}

function randomZephyLine(gameId) {
  const lines = ZEPHY_GAME_LINES[gameId] || ZEPHY_GAME_LINES.default;
  const hints = lines.hints || ZEPHY_GAME_LINES.default.hints;
  return hints[Math.floor(Math.random() * hints.length)];
}

function randomZephyPose(packName) {
  const pack = ZEPHY_POSE_PACKS[packName] || ZEPHY_POSE_PACKS.hint;
  return pack[Math.floor(Math.random() * pack.length)] || "idle";
}

function zephyPoseKind(pose) {
  if (ZEPHY_POSE_PACKS.celebrate.includes(pose)) return "celebrate";
  if (ZEPHY_POSE_PACKS.tryAgain.includes(pose)) return "try-again";
  if (ZEPHY_POSE_PACKS.hint.includes(pose)) return "hint";
  return "idle";
}

function zephyCoachingPackForLine(text) {
  return /\b(again|brave|breathe|slow|careful|lost)\b/i.test(text || "")
    ? "tryAgain"
    : "hint";
}

function zephyStartLine(gameId, missionCount) {
  if (gameId === "home" && missionCount > 0) {
    return `Your badge trail has ${missionCount} ${missionCount === 1 ? "badge" : "badges"}. Pick the next mission with me.`;
  }
  return (ZEPHY_GAME_LINES[gameId] || ZEPHY_GAME_LINES.default).start;
}

function ZephyGameBuddy({
  gameId = "default",
  variant = "game",
  missionCount = 0,
  hasBadges = false,
  onOpenMissionMap,
}) {
  const [line, setLine] = React.useState(
    zephyStartLine(gameId, missionCount),
  );
  const [pose, setPose] = React.useState(() => randomZephyPose("start"));
  const [celebrating, setCelebrating] = React.useState(false);
  const [idlePeeking, setIdlePeeking] = React.useState(false);
  const celebrationTimer = React.useRef(null);
  const idlePeekTimer = React.useRef(null);
  const idlePeekReturnTimer = React.useRef(null);

  const showLine = React.useCallback(
    (nextLine, nextPose = "hint", speak = true) => {
      setLine(nextLine);
      setPose(
        ZEPHY_POSE_PACKS[nextPose]
          ? randomZephyPose(nextPose)
          : ZEPHY_FRAMES[nextPose]
            ? nextPose
            : randomZephyPose("hint"),
      );
      if (speak) speakZephyLine(nextLine);
      window.clearTimeout(celebrationTimer.current);
      celebrationTimer.current = window.setTimeout(() => {
        setPose("idle");
      }, 4200);
    },
    [],
  );

  const celebrate = React.useCallback(
    (message) => {
      const nextLine = message || "Yay! You did it!";
      setCelebrating(true);
      showLine(nextLine, "celebrate", true);
      window.clearTimeout(celebrationTimer.current);
      celebrationTimer.current = window.setTimeout(() => {
        setCelebrating(false);
        setPose("idle");
      }, 2600);
    },
    [showLine],
  );

  React.useEffect(() => {
    const startLine = zephyStartLine(gameId, missionCount);
    showLine(startLine, "start", false);
    return () => {
      window.clearTimeout(celebrationTimer.current);
      window.clearTimeout(idlePeekTimer.current);
      window.clearTimeout(idlePeekReturnTimer.current);
      stopZephySpeech();
    };
  }, [gameId, missionCount, showLine]);

  React.useEffect(() => {
    const stopIfHidden = () => {
      if (document.hidden) stopZephySpeech();
    };
    document.addEventListener("visibilitychange", stopIfHidden);
    window.addEventListener("pagehide", stopZephySpeech);
    return () => {
      document.removeEventListener("visibilitychange", stopIfHidden);
      window.removeEventListener("pagehide", stopZephySpeech);
    };
  }, []);

  React.useEffect(() => {
    const onPraise = (event) => {
      const text = String(event.detail?.text || "").trim();
      celebrate(text || "Yay! You did it!");
    };
    const onTryAgain = (event) => {
      const text = String(event.detail?.text || "").trim();
      showLine(text || "That was super brave. Want to try again with me?", "tryAgain", true);
    };
    window.addEventListener("space:zephy-praise", onPraise);
    window.addEventListener("space:zephy-try-again", onTryAgain);
    return () => {
      window.removeEventListener("space:zephy-praise", onPraise);
      window.removeEventListener("space:zephy-try-again", onTryAgain);
    };
  }, [celebrate, showLine]);

  React.useEffect(() => {
    if (variant !== "home") return undefined;
    const reduceMotion =
      window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches || false;
    if (reduceMotion) return undefined;
    const idleDelay = () => {
      const testDelay = Number(window.__spaceZephyIdleTestDelay);
      if (Number.isFinite(testDelay) && testDelay >= 0) return testDelay;
      return 30000;
    };
    const clearIdleTimers = () => {
      window.clearTimeout(idlePeekTimer.current);
      window.clearTimeout(idlePeekReturnTimer.current);
    };
    const scheduleIdlePeek = () => {
      window.clearTimeout(idlePeekTimer.current);
      idlePeekTimer.current = window.setTimeout(() => {
        setIdlePeeking(true);
        setPose("tailWag");
        idlePeekReturnTimer.current = window.setTimeout(() => {
          setIdlePeeking(false);
          setPose("idle");
          scheduleIdlePeek();
        }, 3600);
      }, idleDelay());
    };
    const resetIdlePeek = () => {
      clearIdleTimers();
      setIdlePeeking(false);
      scheduleIdlePeek();
    };
    const activityEvents = ["pointerdown", "keydown", "touchstart"];
    activityEvents.forEach((eventName) =>
      window.addEventListener(eventName, resetIdlePeek, { passive: true }),
    );
    scheduleIdlePeek();
    return () => {
      clearIdleTimers();
      activityEvents.forEach((eventName) =>
        window.removeEventListener(eventName, resetIdlePeek),
      );
    };
  }, [variant]);

  const nudge = () => {
    const nextLine = randomZephyLine(gameId);
    showLine(nextLine, zephyCoachingPackForLine(nextLine), true);
    if (window.playKidSound) window.playKidSound("boop");
  };
  const openMissionMap = () => {
    if (typeof onOpenMissionMap === "function") {
      showLine("Mission Map ready. Let us choose the next stop.", "hint", true);
      onOpenMissionMap();
    }
  };
  const poseKind = zephyPoseKind(pose);
  const classes = [
    "zephy-buddy",
    `zephy-buddy-${variant}`,
    hasBadges ? "zephy-buddy-has-badges" : "",
    celebrating ? "celebrating" : "",
    idlePeeking ? "zephy-idle-peek" : "",
  ]
    .filter(Boolean)
    .join(" ");

  return (
    <div
      className={classes}
      aria-live="polite"
    >
      {celebrating ? (
        <div className="zephy-confetti" aria-hidden="true">
          {Array.from({ length: 12 }).map((_, index) => (
            <span key={index} />
          ))}
        </div>
      ) : null}
      {celebrating ? <div className="zephy-banner">You did it!</div> : null}
      <button
        type="button"
        className={`zephy-sprite zephy-pose-${pose} zephy-kind-${poseKind}`}
        style={zephyFrameStyle(pose)}
        onClick={nudge}
        aria-label="Ask Zephy for a gentle hint"
      />
      <div className="zephy-bubble">
        <span>{line}</span>
        {typeof onOpenMissionMap === "function" ? (
          <button
            type="button"
            className="zephy-action"
            onClick={openMissionMap}
          >
            Pick mission
          </button>
        ) : null}
      </div>
    </div>
  );
}

window.SpaceExplorerZephyBuddy = ZephyGameBuddy;
