"use client";

import {
  CSSProperties,
  FormEvent,
  PointerEvent as ReactPointerEvent,
  WheelEvent as ReactWheelEvent,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import seed from "../data/personas.json";
import { DEFAULT_DESIGN_PERSONA, isDesignPersonaId } from "@/lib/design-personas";
import styles from "./studio-field-03.module.css";

type ViewTransform = { x: number; y: number; scale: number };
type PlaceKind = "Organization" | "Alliance" | "Program" | "Project" | "Relationship";
type FieldPlace = {
  id: string;
  kind: PlaceKind;
  title: string;
  note: string;
  description: string;
  detail: string;
  x: number;
  y: number;
  size: "large" | "medium";
  accent: string;
  mark: string;
};

const FIELD_SIZE = { width: 1760, height: 1060 };
const START: ViewTransform = { x: -110, y: -110, scale: .78 };
const RESERVED_SEQUENCE = [0, 1, 3, 2, 4, 1];

const places: FieldPlace[] = [
  {
    id: "kinship",
    kind: "Organization",
    title: "Kinship Duna",
    note: "Your founding home · 6 people near",
    description: "Your founding Organization: relationships, shared care, and the work that begins close to home.",
    detail: "6 direct invitees · 2 active contexts",
    x: 400,
    y: 500,
    size: "large",
    accent: "#d8aa62",
    mark: "K",
  },
  {
    id: "dunaversity",
    kind: "Organization",
    title: "Dunaversity",
    note: "Learning with living Wisdom",
    description: "A place where Wisdom is practiced, carried forward, and changed through contribution.",
    detail: "3 Programs visible · 1 change awaiting you",
    x: 980,
    y: 350,
    size: "large",
    accent: "#f0c56c",
    mark: "D",
  },
  {
    id: "service",
    kind: "Alliance",
    title: "Service Alliance",
    note: "Shared operations · people active now",
    description: "A formal collaboration where Alice helps organize work and make authority inspectable.",
    detail: "1 grant awaiting Alice · Bob dependency",
    x: 1370,
    y: 650,
    size: "medium",
    accent: "#ef8f72",
    mark: "S",
  },
  {
    id: "consentful",
    kind: "Program",
    title: "Consentful Systems",
    note: "Alice is catalyzing",
    description: "A living body of practice around plain consent, inspectable authority, and durable institutional memory.",
    detail: "Presence v1.1 is ready to inspect",
    x: 720,
    y: 830,
    size: "medium",
    accent: "#dcae7c",
    mark: "C",
  },
  {
    id: "alice-bob",
    kind: "Relationship",
    title: "Alice + Bob",
    note: "A trusted room for two",
    description: "Your Relationship with Bob has its own context, memory, and directional boundaries.",
    detail: "Connected by Handshake · private context",
    x: 1280,
    y: 220,
    size: "medium",
    accent: "#b9b2a6",
    mark: "A·B",
  },
];

const paths = [
  { left: 310, top: 390, width: 750, height: 300, rotate: -10 },
  { left: 650, top: 270, width: 760, height: 470, rotate: 8 },
  { left: 520, top: 430, width: 880, height: 500, rotate: 4 },
  { left: 890, top: 160, width: 470, height: 300, rotate: -6 },
];

export default function StudioField03() {
  const [personaId, setPersonaId] = useState(DEFAULT_DESIGN_PERSONA);
  const [transform, setTransform] = useState<ViewTransform>(START);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [viewportSize, setViewportSize] = useState({ width: 980, height: 720 });
  const [computeTick, setComputeTick] = useState(0);
  const [input, setInput] = useState("");
  const [kiReply, setKiReply] = useState<string | null>(null);
  const viewportRef = useRef<HTMLDivElement | null>(null);
  const dragRef = useRef<{ id: number; clientX: number; clientY: number; x: number; y: number } | null>(null);

  useEffect(() => {
    const value = new URLSearchParams(window.location.search).get("persona");
    if (isDesignPersonaId(value)) setPersonaId(value);
  }, []);

  useEffect(() => {
    const viewport = viewportRef.current;
    if (!viewport) return;
    const observer = new ResizeObserver(([entry]) => {
      setViewportSize({ width: entry.contentRect.width, height: entry.contentRect.height });
    });
    observer.observe(viewport);
    return () => observer.disconnect();
  }, []);

  useEffect(() => {
    const interval = window.setInterval(() => setComputeTick((value) => value + 1), 3400);
    return () => window.clearInterval(interval);
  }, []);

  const persona = useMemo(() => seed.personas.find((item) => item.id === personaId) ?? seed.personas[0], [personaId]);
  const selected = places.find((place) => place.id === selectedId) ?? null;
  const reserved = RESERVED_SEQUENCE[computeTick % RESERVED_SEQUENCE.length];
  const availableCompute = persona.resources.wallet.kiduna - reserved;

  const setScale = (nextScale: number) => {
    const viewport = viewportRef.current;
    if (!viewport) return;
    const rect = viewport.getBoundingClientRect();
    const centerX = rect.width / 2;
    const centerY = rect.height / 2;
    setTransform((current) => {
      const scale = Math.min(1.9, Math.max(.5, nextScale));
      const worldX = (centerX - current.x) / current.scale;
      const worldY = (centerY - current.y) / current.scale;
      return { scale, x: centerX - worldX * scale, y: centerY - worldY * scale };
    });
  };

  const handleWheel = (event: ReactWheelEvent<HTMLDivElement>) => {
    event.preventDefault();
    const zoomGesture = event.ctrlKey || (Math.abs(event.deltaX) < 1 && Math.abs(event.deltaY) > 60);
    if (!zoomGesture) {
      setTransform((current) => ({ ...current, x: current.x - event.deltaX, y: current.y - event.deltaY }));
      return;
    }
    const rect = event.currentTarget.getBoundingClientRect();
    const pointerX = event.clientX - rect.left;
    const pointerY = event.clientY - rect.top;
    setTransform((current) => {
      const factor = Math.exp(-event.deltaY * .0012);
      const scale = Math.min(1.9, Math.max(.5, current.scale * factor));
      const worldX = (pointerX - current.x) / current.scale;
      const worldY = (pointerY - current.y) / current.scale;
      return { scale, x: pointerX - worldX * scale, y: pointerY - worldY * scale };
    });
  };

  const handlePointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {
    if ((event.target as HTMLElement).closest("button, input")) return;
    event.currentTarget.setPointerCapture(event.pointerId);
    dragRef.current = { id: event.pointerId, clientX: event.clientX, clientY: event.clientY, x: transform.x, y: transform.y };
  };

  const handlePointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {
    const drag = dragRef.current;
    if (!drag || drag.id !== event.pointerId) return;
    setTransform((current) => ({ ...current, x: drag.x + event.clientX - drag.clientX, y: drag.y + event.clientY - drag.clientY }));
  };

  const endDrag = (event: ReactPointerEvent<HTMLDivElement>) => {
    if (dragRef.current?.id === event.pointerId) dragRef.current = null;
  };

  const choosePlace = (place: FieldPlace) => {
    setSelectedId(place.id);
    setKiReply(null);
  };

  const focusPlace = (place: FieldPlace) => {
    const viewport = viewportRef.current;
    if (!viewport) return;
    const rect = viewport.getBoundingClientRect();
    const scale = Math.max(transform.scale, 1.05);
    const destinationX = rect.width * .44;
    const destinationY = rect.height * .54;
    setSelectedId(place.id);
    setKiReply(null);
    setTransform({ scale, x: destinationX - place.x * scale, y: destinationY - place.y * scale });
  };

  const submit = (event: FormEvent) => {
    event.preventDefault();
    const request = input.trim();
    if (!request) return;
    const normalized = request.toLowerCase();
    setInput("");
    const match = places.find((place) => normalized.includes(place.title.toLowerCase().split(" ")[0]));
    if (match) {
      focusPlace(match);
      return;
    }
    if (normalized.includes("attention") || normalized.includes("next")) {
      focusPlace(places[1]);
      return;
    }
    setKiReply(`i heard “${request}.” Choose one place in the Field and i’ll bring its living context closer.`);
  };

  const initialPlace = places[1];
  const kiText = kiReply ?? (selected
    ? selected.description
    : `${persona.publicCodeName}, five places are near. Dunaversity has one change that may need your attention.`);
  const actionPlace = selected ?? initialPlace;
  const actionLabel = selected ? `Move closer to ${selected.title}` : "Move toward Dunaversity";

  const panelPosition = selected ? getPanelPosition(selected, transform, viewportSize) : null;

  return <main className={styles.stage}>
    <section
      className={styles.viewport}
      ref={viewportRef}
      onWheel={handleWheel}
      onPointerDown={handlePointerDown}
      onPointerMove={handlePointerMove}
      onPointerUp={endDrag}
      onPointerCancel={endDrag}
      aria-label="The Field as Alice"
    >
      <header className={styles.orientation}>
        <small>HERE · THIS MOMENT</small>
        <h1>The Field is alive</h1>
        <p>Move toward one place. The rest will stay near.</p>
      </header>

      <aside className={styles.compute} aria-label="Available Compute">
        <div className={styles.computeValue}>
          <span aria-hidden="true">⌁</span>
          <div><small>COMPUTE · AVAILABLE</small><strong>{availableCompute.toLocaleString()} <em>$KIDUNA</em></strong></div>
          <i className={styles.liveDot} title="Live fixture" />
        </div>
        <p>{reserved ? `${reserved} $KIDUNA in motion` : "Settled now"} · live fixture</p>
        <button type="button" onClick={() => window.location.assign(`/outside/resources?persona=${personaId}`)}>Go To Resources</button>
      </aside>

      <div
        className={styles.world}
        style={{ width: FIELD_SIZE.width, height: FIELD_SIZE.height, transform: `translate3d(${transform.x}px,${transform.y}px,0) scale(${transform.scale})` }}
      >
        {paths.map((path, index) => <i key={index} className={styles.path} style={{ left: path.left, top: path.top, width: path.width, height: path.height, transform: `rotate(${path.rotate}deg)`, animationDelay: `${index * -2.3}s` }} />)}
        {Array.from({ length: 28 }, (_, index) => <i key={`mote-${index}`} className={styles.mote} style={{ left: `${4 + ((index * 131) % 92)}%`, top: `${5 + ((index * 79) % 86)}%`, animationDelay: `${(index % 11) * -.7}s`, animationDuration: `${7 + (index % 5)}s` }} />)}
        {places.map((place, index) => <PlaceButton key={place.id} place={place} index={index} selected={selectedId === place.id} onSelect={() => choosePlace(place)} onApproach={() => focusPlace(place)} />)}
      </div>

      {selected && panelPosition && <aside
        className={styles.realmPanel}
        style={{ left: panelPosition.left, top: panelPosition.top, "--panel-accent": selected.accent } as CSSProperties}
        aria-live="polite"
      >
        <button type="button" className={styles.closePanel} onClick={() => setSelectedId(null)} aria-label="Close panel">×</button>
        <small>{selected.kind}</small>
        <h2>{selected.title}</h2>
        <p>{selected.description}</p>
        <div>{selected.detail}</div>
      </aside>}

      <div className={styles.viewControls} aria-label="Field view controls">
        <button type="button" onClick={() => setScale(transform.scale * 1.17)} aria-label="Move closer">＋</button>
        <button type="button" onClick={() => setScale(transform.scale / 1.17)} aria-label="Move farther away">−</button>
        <button type="button" onClick={() => setTransform(START)}>Center</button>
      </div>
      <div className={styles.navigationHint}><span aria-hidden="true">↔</span><p><b>Travel through the Field</b><small>Drag or two-finger swipe · pinch or wheel to move closer</small></p></div>
    </section>

    <aside className={styles.ki} aria-label="Ki">
      <header>
        <img src="/ki-avatar-glyph.png" alt="" />
        <div><small>KI · HERE WITH {persona.publicCodeName.toUpperCase()}</small><strong>{selected?.title ?? "The Field"}</strong></div>
      </header>
      <div className={styles.kiPresence} aria-hidden="true"><i /><i /><i /></div>
      <p className={styles.kiMessage}>{kiText}</p>
      <button className={styles.kiAction} type="button" onClick={() => focusPlace(actionPlace)}>{actionLabel}</button>
      <form onSubmit={submit}>
        <input value={input} onChange={(event) => setInput(event.target.value)} aria-label="Talk with Ki" placeholder="Tell Ki where you want to go…" />
        <button type="submit" aria-label="Send">↑</button>
      </form>
      <footer><i /> Field present <span>·</span> Alice’s permitted view</footer>
    </aside>
  </main>;
}

function getPanelPosition(place: FieldPlace, transform: ViewTransform, viewport: { width: number; height: number }) {
  const nodeX = transform.x + place.x * transform.scale;
  const nodeY = transform.y + place.y * transform.scale;
  const panelWidth = Math.min(310, viewport.width - 32);
  const panelHeight = 220;
  const placePanelToRight = nodeX < viewport.width * .6;
  const preferredLeft = placePanelToRight ? nodeX + 62 : nodeX - panelWidth - 62;
  return {
    left: Math.max(16, Math.min(viewport.width - panelWidth - 16, preferredLeft)),
    top: Math.max(142, Math.min(viewport.height - panelHeight - 24, nodeY - 94)),
  };
}

function PlaceButton({ place, index, selected, onSelect, onApproach }: { place: FieldPlace; index: number; selected: boolean; onSelect: () => void; onApproach: () => void }) {
  const style = { left: place.x, top: place.y, "--accent": place.accent, "--drift-delay": `${index * -1.7}s` } as CSSProperties;
  return <button
    type="button"
    className={`${styles.place} ${styles[place.size]} ${selected ? styles.selected : ""}`}
    style={style}
    onClick={onSelect}
    onDoubleClick={onApproach}
    aria-label={`${place.kind}: ${place.title}. ${place.note}. Select for context; double-click to move closer.`}
  >
    <span className={styles.orbit} aria-hidden="true" />
    <span className={styles.placeBody} aria-hidden="true"><i /><b>{place.mark}</b></span>
    <span className={styles.placeLabel}><small>{place.kind}</small><strong>{place.title}</strong><em>{place.note}</em></span>
  </button>;
}
