// Pack-Your-Suitcase-For-Mars - short kid-mode drag-and-bounce loop.

const MARS_SUITCASE_ITEMS = [
  {
    id: "jacket",
    label: "Warm jacket",
    icon: "J",
    keep: true,
    note: "Warm jacket packed. Mars nights are chilly.",
  },
  {
    id: "oxygen",
    label: "Oxygen tank",
    icon: "O2",
    keep: true,
    note: "Oxygen tank packed. Astronauts bring air with them.",
  },
  {
    id: "sunscreen",
    label: "Sunscreen",
    icon: "SPF",
    keep: true,
    note: "Sunscreen packed. Mars sunlight still reaches your suit.",
  },
  {
    id: "snorkel",
    label: "Snorkel",
    icon: "S",
    keep: false,
    note: "Snorkel can stay home for this dry Mars trip.",
  },
];

function MarsSuitcaseLevel({ onExit }) {
  const [packedIds, setPackedIds] = useState([]);
  const [drag, setDrag] = useState(null);
  const [bounceId, setBounceId] = useState(null);
  const [message, setMessage] = useState("Pack the Mars bag.");
  const [launched, setLaunched] = useState(false);
  const bagRef = useRef(null);
  const bounceTimerRef = useRef(null);
  const messageTimerRef = useRef(null);

  const neededItems = MARS_SUITCASE_ITEMS.filter((item) => item.keep);
  const ready = neededItems.every((item) => packedIds.includes(item.id));
  const packedItems = MARS_SUITCASE_ITEMS.filter((item) =>
    packedIds.includes(item.id),
  );

  useEffect(
    () => () => {
      if (bounceTimerRef.current) clearTimeout(bounceTimerRef.current);
      if (messageTimerRef.current) clearTimeout(messageTimerRef.current);
    },
    [],
  );

  useEffect(() => {
    if (!drag) return undefined;
    const move = (event) => {
      const point = pointFromPointer(event);
      setDrag((current) => (current ? { ...current, x: point.x, y: point.y } : null));
    };
    const up = (event) => {
      const point = pointFromPointer(event);
      finishDrag(point);
    };
    window.addEventListener("pointermove", move);
    window.addEventListener("pointerup", up);
    window.addEventListener("pointercancel", up);
    return () => {
      window.removeEventListener("pointermove", move);
      window.removeEventListener("pointerup", up);
      window.removeEventListener("pointercancel", up);
    };
  }, [drag]);

  function pointFromPointer(event) {
    return { x: event.clientX, y: event.clientY };
  }

  function isPointInBag(point) {
    const rect = bagRef.current?.getBoundingClientRect();
    if (!rect) return false;
    return (
      point.x >= rect.left &&
      point.x <= rect.right &&
      point.y >= rect.top &&
      point.y <= rect.bottom
    );
  }

  function pulseBounce(itemId) {
    setBounceId(itemId);
    if (bounceTimerRef.current) clearTimeout(bounceTimerRef.current);
    bounceTimerRef.current = setTimeout(() => setBounceId(null), 620);
  }

  function showMessage(nextMessage, nextReady = ready) {
    setMessage(nextMessage);
    if (messageTimerRef.current) clearTimeout(messageTimerRef.current);
    messageTimerRef.current = setTimeout(() => {
      setMessage(nextReady ? "Mars bag is ready." : "Pack the Mars bag.");
    }, 2200);
  }

  function tryPackItem(itemId, inBag) {
    const item = MARS_SUITCASE_ITEMS.find((entry) => entry.id === itemId);
    if (!item || packedIds.includes(item.id)) return;
    if (!inBag) {
      pulseBounce(item.id);
      showMessage("Aim for the open duffel.");
      if (typeof playKidSound === "function") playKidSound("pop");
      return;
    }
    if (!item.keep) {
      pulseBounce(item.id);
      showMessage(item.note);
      if (typeof playKidSound === "function") playKidSound("pop");
      return;
    }
    const nextPacked = [...packedIds, item.id];
    setPackedIds(nextPacked);
    showMessage(item.note, nextPacked.length >= neededItems.length);
    if (typeof playKidSound === "function") playKidSound("chime");
  }

  function startDrag(item, event) {
    if (packedIds.includes(item.id) || launched) return;
    event.preventDefault();
    const point = pointFromPointer(event);
    setDrag({ itemId: item.id, x: point.x, y: point.y });
    setBounceId(null);
    if (typeof playKidSound === "function") playKidSound("boop");
  }

  function finishDrag(point) {
    if (!drag) return;
    tryPackItem(drag.itemId, isPointInBag(point));
    setDrag(null);
  }

  function reset() {
    setPackedIds([]);
    setDrag(null);
    setBounceId(null);
    setLaunched(false);
    setMessage("Pack the Mars bag.");
  }

  function launchBag() {
    if (!ready) return;
    setLaunched(true);
    setMessage("Mars bag is ready!");
    if (typeof playKidSound === "function") playKidSound("sparkle");
  }

  return (
    <section className="mars-suitcase-level" aria-label="Pack Your Suitcase For Mars">
      <button className="mars-suitcase-back" type="button" onClick={onExit}>
        Back
      </button>
      <div className="mars-suitcase-header">
        <span>Kid mode</span>
        <strong>Mars Suitcase</strong>
        <p>{ready ? "Three things are glowing in the bag." : "Three things ride to Mars."}</p>
      </div>

      <div className={`mars-suitcase-flight ${launched ? "launched" : ""}`} aria-hidden="true">
        <div className="mars-suitcase-rocket">ROCKET</div>
        <div className="mars-suitcase-flight-bag">
          {packedItems.map((item) => (
            <i key={item.id}>{item.icon}</i>
          ))}
        </div>
      </div>

      <div className="mars-suitcase-board">
        <div
          ref={bagRef}
          className={`mars-suitcase-bag ${ready ? "ready" : ""}`}
          aria-label={`${packedIds.length} of ${neededItems.length} Mars items packed`}
        >
          <div className="mars-suitcase-bag-lid" />
          <div className="mars-suitcase-slots">
            {neededItems.map((item) => (
              <div
                key={item.id}
                className={packedIds.includes(item.id) ? "packed" : ""}
              >
                {packedIds.includes(item.id) ? item.icon : ""}
              </div>
            ))}
          </div>
          <strong>{packedIds.length}/{neededItems.length}</strong>
        </div>

        <div className="mars-suitcase-tray" aria-label="Suitcase items">
          {MARS_SUITCASE_ITEMS.map((item) => {
            const packed = packedIds.includes(item.id);
            return (
              <button
                key={item.id}
                type="button"
                className={`${packed ? "packed" : ""} ${bounceId === item.id ? "bounce" : ""}`}
                onPointerDown={(event) => startDrag(item, event)}
                onClick={() => tryPackItem(item.id, true)}
                disabled={packed || launched}
                aria-label={`${item.label}${packed ? " packed" : ""}`}
              >
                <b>{item.icon}</b>
                <span>{item.label}</span>
              </button>
            );
          })}
        </div>
      </div>

      <div className="mars-suitcase-status" role="status" aria-live="polite">
        <strong>{message}</strong>
        <span>{ready ? "Launch the bag when you are ready." : "Useful items glow into the duffel."}</span>
      </div>

      <div className="mars-suitcase-actions">
        <button type="button" onClick={launchBag} disabled={!ready || launched}>
          Launch bag
        </button>
        <button type="button" onClick={reset}>
          Pack again
        </button>
      </div>

      {launched ? (
        <div className="mars-suitcase-finish" role="status" aria-live="polite">
          <strong>Mars bag is ready!</strong>
          <span>Jacket, air, and sunscreen are riding along.</span>
        </div>
      ) : null}

      {drag ? (
        <div
          className="mars-suitcase-drag"
          style={{ left: drag.x, top: drag.y }}
          aria-hidden="true"
        >
          {MARS_SUITCASE_ITEMS.find((item) => item.id === drag.itemId)?.icon}
        </div>
      ) : null}
    </section>
  );
}

window.MarsSuitcaseLevel = MarsSuitcaseLevel;
