import { useEffect, useRef, useState } from "react";
import { WarpBubbleScene } from "../r3f/warp/WarpBubbleScene";
import {
  advanceTravelSession,
  getTravelSessionIdFromUrl,
  loadTravelSession,
  saveTravelSession,
  setTravelMode,
  startJump,
  withTravelSession,
  type TravelSession,
} from "../r3f/navigation/travelSession";
import { getGameSliceSessionIdFromUrl, loadGameSliceSession, withGameSliceSession } from "../game-slice/gameSliceState";
import { syncSliceFromTravelArrival } from "../game-slice/sliceNavigationBridge";
import { SliceDemoLinks } from "../game-slice/ui/SliceDemoLinks";
import type { GameSliceSession } from "../game-slice/types";

export function WarpTravelDemo() {
  const [travelSession, setTravelSession] = useState<TravelSession | null>(null);
  const [invalidSession, setInvalidSession] = useState(false);
  const [sliceSession, setSliceSession] = useState<GameSliceSession | null>(null);
  const lastPersistedAt = useRef(0);

  useEffect(() => {
    const navSessionId = getTravelSessionIdFromUrl();
    const sliceSessionId = getGameSliceSessionIdFromUrl();
    const loadedSlice = sliceSessionId ? loadGameSliceSession(sliceSessionId) : null;
    const loaded = navSessionId ? loadTravelSession(navSessionId) : null;
    if (loadedSlice) setSliceSession(loadedSlice);
    if (!loaded) {
      setInvalidSession(true);
      return;
    }

    const session = loaded.status === "in_transit" ? setTravelMode(loaded, "warp_bubble") : loaded;
    saveTravelSession(session);
    setTravelSession(session);
    if (session.status === "arrived") {
      const synced = syncSliceFromTravelArrival(sliceSessionId, session);
      if (synced) setSliceSession(synced);
    }
  }, []);

  useEffect(() => {
    if (!travelSession || travelSession.status !== "in_transit") return;
    let raf = 0;
    let last = performance.now();

    const tick = (now: number) => {
      const dt = Math.min(0.08, (now - last) / 1000);
      last = now;
      setTravelSession((prev) => {
        if (!prev || prev.status !== "in_transit") return prev;
        const next = advanceTravelSession(prev, dt);
        if (now - lastPersistedAt.current > 250 || next.status === "arrived") {
          saveTravelSession(next);
          if (next.status === "arrived") {
            const synced = syncSliceFromTravelArrival(getGameSliceSessionIdFromUrl(), next);
            if (synced) setSliceSession(synced);
          }
          lastPersistedAt.current = now;
        }
        return next;
      });
      raf = requestAnimationFrame(tick);
    };

    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [travelSession?.id, travelSession?.status]);

  const openStarMap = () => {
    if (!travelSession) {
      window.location.href = sliceSession ? withGameSliceSession("/docs/demos/starmap", sliceSession.id) : "/docs/demos/starmap";
      return;
    }
    const session = setTravelMode(travelSession, travelSession.status === "in_transit" ? "star_map_tracking" : "star_map_planning");
    saveTravelSession(session);
    const url = withTravelSession("/docs/demos/starmap", session.id);
    window.location.href = sliceSession ? withGameSliceSession(url, sliceSession.id) : url;
  };

  const openMovement = () => {
    if (!travelSession) {
      window.location.href = sliceSession ? withGameSliceSession("/docs/demos/movement", sliceSession.id) : "/docs/demos/movement";
      return;
    }
    const poi = travelSession.destinationPoi;
    const target = poi && travelSession.status === "arrived"
      ? `/docs/demos/movement?navSession=${travelSession.id}&systemId=${encodeURIComponent(poi.systemId)}&poiId=${encodeURIComponent(poi.poiId)}`
      : withTravelSession("/docs/demos/movement", travelSession.id);
    window.location.href = sliceSession ? withGameSliceSession(target, sliceSession.id) : target;
  };

  const beginJump = () => {
    if (!travelSession) return;
    const session = setTravelMode(startJump(travelSession), "warp_bubble");
    saveTravelSession(session);
    setTravelSession(session);
  };

  const route = travelSession?.route ?? null;
  const activeSegment = route?.segments[travelSession?.activeSegmentIndex ?? 0] ?? null;
  const totalProgress = Math.round((travelSession?.totalProgress ?? 0) * 100);
  const segmentProgress = Math.round((travelSession?.segmentProgress ?? 0) * 100);

  if (invalidSession || !travelSession) {
    return (
      <div style={{ width: "100%", height: "100vh", background: "#040810", color: "#d4dce8", display: "grid", placeItems: "center" }}>
        <div style={{ width: 360, background: "rgba(15,22,35,0.9)", border: "1px solid var(--border)", borderRadius: 8, padding: 16 }}>
          <h2 style={{ marginTop: 0 }}>WARP</h2>
          <p style={{ color: "var(--fg-dim)" }}>Navigation session unavailable</p>
          <button onClick={openStarMap}>Open Star Map</button>
          <button onClick={openMovement} style={{ marginLeft: 8 }}>Open Movement</button>
        </div>
      </div>
    );
  }

  return (
    <div style={{ position: "relative", width: "100%", height: "100vh", background: "#040810", overflow: "hidden", color: "#d4dce8" }}>
      <WarpBubbleScene
        route={route}
        activeSegmentIndex={travelSession.activeSegmentIndex}
        segmentProgress={travelSession.segmentProgress}
        totalProgress={travelSession.totalProgress}
      />
      <div style={{ position: "absolute", inset: 0, zIndex: 1, display: "grid", gridTemplateRows: "44px 1fr 118px", gap: 8, padding: 8, pointerEvents: "none" }}>
        <div style={{ display: "flex", gap: 14, alignItems: "center", padding: "0 12px", background: "rgba(8,12,20,0.86)", border: "1px solid var(--border)", borderRadius: 8, pointerEvents: "auto" }}>
          <button onClick={() => { window.location.href = "/docs/overview"; }}>DOCS</button>
          <strong>WARP</strong>
          <span>{activeSegment ? `${activeSegment.from.name} -> ${activeSegment.to.name}` : route ? route.destination.name : "No route"}</span>
          <span>Jump {route ? Math.min(travelSession.activeSegmentIndex + 1, route.segments.length) : 0}/{route?.segments.length ?? 0}</span>
          <span>Total {totalProgress}%</span>
          <button onClick={openStarMap} style={{ marginLeft: "auto" }}>Track on Star Map</button>
          <button onClick={openMovement} disabled={travelSession.status !== "arrived"}>Open Movement</button>
          <button onClick={openStarMap}>Back to Star Map</button>
        </div>
        {travelSession.status !== "in_transit" && (
          <div style={{ width: 360, pointerEvents: "auto", background: "rgba(15,22,35,0.88)", border: "1px solid var(--border)", borderRadius: 8, padding: 14, alignSelf: "start" }}>
            <h3 style={{ marginTop: 0 }}>{travelSession.status === "arrived" ? travelSession.arrivalMessage ?? "Arrived" : "Route Ready"}</h3>
            {route && <p style={{ color: "var(--fg-dim)" }}>{route.systems.map((system) => system.name).join(" -> ")}</p>}
            {travelSession.status === "planned" && <button onClick={beginJump} disabled={!route}>Start Jump</button>}
            {travelSession.status === "arrived" && <button onClick={openMovement}>Open Movement</button>}
            {sliceSession && <button onClick={() => { window.location.href = withGameSliceSession("/docs/demos/game-loop", sliceSession.id); }} style={{ marginLeft: 8 }}>Return to Loop</button>}
          </div>
        )}
        {sliceSession && (
          <div style={{ alignSelf: "start", justifySelf: "center", pointerEvents: "auto", width: 720, maxWidth: "calc(100vw - 32px)" }}>
            <SliceDemoLinks session={sliceSession} compact />
          </div>
        )}
        <div style={{ alignSelf: "end", background: "rgba(8,12,20,0.78)", border: "1px solid var(--border)", borderRadius: 8, pointerEvents: "auto", padding: 12 }}>
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 8 }}>
            <span>{travelSession.status === "arrived" ? travelSession.arrivalMessage ?? "ARRIVED" : "WARP BUBBLE"}</span>
            <span>Segment {segmentProgress}%</span>
          </div>
          <div style={{ height: 8, background: "#111827", borderRadius: 999, overflow: "hidden" }}>
            <div style={{ width: `${totalProgress}%`, height: "100%", background: travelSession.status === "arrived" ? "#22c55e" : "#22d3ee" }} />
          </div>
        </div>
      </div>
    </div>
  );
}
