// room.jsx — interactive desk scene + built-in drag/resize POSITION EDITOR.
//
// EDIT MODE: press "e" (or open with #edit) to toggle. Every object becomes
// draggable; drag the body to move, drag the bottom-right handle to resize,
// click to select then use arrow keys to nudge (Shift = bigger steps).
// The panel shows live coordinates; "Copy coords" puts them on your clipboard
// to paste back to me. Edits persist in localStorage; "Reset" restores defaults.

// Boxes are % of a 1104 x 618 frame.  kind: 'obj' (glows + navigates) |
// 'static' (the desk base) | 'hotspot' (region baked into the desk image).
const DEFAULT_LAYOUT = [
  { id: 'window',   kind: 'obj',    src: 'room/window.png',  section: 'education',  box: [16.98, 16.84, 20.59, 46.62], z: 1,  anchor: [27, 29],  label: 'Education' },
  { id: 'agtech',   kind: 'obj',    src: 'room/agtech.png',  section: 'projects',   box: [64.24, 18.49, 16.4, 67.5],   z: 2,  anchor: [72, 20],  label: 'Projects' },
  { id: 'desk',     kind: 'static', src: 'room/desk.png',    section: null,         box: [34.51, 13.52, 31.9, 78],     z: 3,  anchor: null,      label: 'Desk' },
  { id: 'trophies', kind: 'obj',    src: 'room/trophies.png',section: 'awards',     box: [39.26, 13.43, 23.6, 13.9],   z: 5,  anchor: [50, 13],  label: 'Awards' },
  { id: 'laptop',   kind: 'obj',    src: 'room/laptop.png',  section: 'experience', box: [42.26, 52.26, 15.29, 14.45], z: 7,  anchor: [51, 53],  label: 'Experience' },
  { id: 'guitar',   kind: 'obj',    src: 'room/object.png',  section: 'contact',    box: [28.38, 53.73, 7.3, 37.5],    z: 8,  anchor: [32, 55],  label: "Let's connect" },
  { id: 'books',    kind: 'obj',    src: 'room/books.png',   section: 'skills',     box: [39.4, 25.31, 24, 13.6],      z: 10, anchor: [51, 25],  label: 'Skills', cls: 'bookglow', group: 'books' },
  { id: 'books2',   kind: 'obj',    src: 'room/books2.png',  section: 'skills',     box: [50.3, 36.64, 14, 9.5],       z: 10, anchor: null,      label: 'Skills', cls: 'bookglow', group: 'books', noMarker: true },
  { id: 'chair',    kind: 'obj',    src: 'room/chair.png',   section: 'about',      box: [48.04, 58.14, 21, 44],       z: 12, anchor: [58, 59],  label: 'About' },
  { id: 'lamp',     kind: 'hotspot',src: null,               section: '__theme',    box: [35.64, 43.74, 11, 22],       z: 10, anchor: [41, 44],  label: 'Lights' },
];

const LS_KEY = 'sofi-room-layout-v3';

function loadLayout() {
  // DEFAULT_LAYOUT is authoritative (coordinates are authored in code).
  // The in-session position editor still updates state for dev use, but a
  // stale saved copy must never override hand-tuned coordinates on load.
  return DEFAULT_LAYOUT.map((d) => ({ ...d }));
}

/* ---------- normal (live) rendering ---------- */
function retryImg(e) {
  const img = e.target;
  const n = (img.__tries || 0) + 1;
  if (n > 4) return;
  img.__tries = n;
  const base = img.src.split('?')[0];
  setTimeout(() => { img.src = base + '?r=' + n; }, 250 * n);
}

// Resolve an asset path through the standalone bundler's __resources map when
// present (blob URLs), else fall back to the literal relative path.
function srcUrl(path) {
  if (!path) return path;
  const r = window.__resources;
  if (r) {
    const key = 'room_' + path.split('/').pop().replace(/\.[^.]+$/, '');
    if (r[key]) return r[key];
  }
  return path;
}

function LiveObject({ item, onNavigate, onToggleTheme, hoverGroup, setHoverGroup }) {
  const [l, t, w, h] = item.box;
  const style = { left: l + '%', top: t + '%', width: w + '%', height: h + '%', zIndex: item.z };
  if (item.kind === 'static') {
    return <div className="obj static" style={style}><img src={srcUrl(item.src)} alt="desk" draggable="false" onError={retryImg} /></div>;
  }
  const isTheme = item.section === '__theme';
  const onClick = () => (isTheme ? onToggleTheme() : onNavigate(item.section));
  if (item.kind === 'hotspot') {
    const [ax, ay] = item.anchor;
    return (
      <React.Fragment>
        <button className="obj hotspot" style={style} onClick={onClick} aria-label={item.label}>
          <span className="halo"></span>
        </button>
        <div className="marker hs-marker" style={{ left: ax + '%', top: ay + '%' }}>
          <span className="label">{item.label}</span><span className="leader"></span>
        </div>
      </React.Fragment>
    );
  }
  const grouped = item.group && hoverGroup === item.group;
  const groupProps = item.group
    ? { onMouseEnter: () => setHoverGroup(item.group), onMouseLeave: () => setHoverGroup(null) }
    : {};
  return (
    <React.Fragment>
      <button className={'obj hot ' + (item.cls || '') + (grouped ? ' glow' : '')} style={style}
        onClick={onClick} aria-label={item.label} {...groupProps}>
        <img src={srcUrl(item.src)} alt={item.id} draggable="false" onError={retryImg} />
      </button>
      {!item.noMarker && item.anchor && (
        <div className={'marker' + (grouped ? ' show' : '')} style={{ left: item.anchor[0] + '%', top: item.anchor[1] + '%' }}>
          <span className="label">{item.label}</span><span className="leader"></span>
        </div>
      )}
    </React.Fragment>
  );
}

/* ---------- edit-mode rendering ---------- */
function EditObject({ item, selected, onSelect, onDrag, onResize }) {
  const [l, t, w, h] = item.box;
  const style = { left: l + '%', top: t + '%', width: w + '%', height: h + '%', zIndex: selected ? 999 : item.z };

  const startDrag = (e) => {
    e.preventDefault(); e.stopPropagation();
    onSelect(item.id);
    const frame = e.currentTarget.closest('.room-frame').getBoundingClientRect();
    const x0 = e.clientX, y0 = e.clientY, l0 = l, t0 = t;
    const move = (ev) => {
      const dl = ((ev.clientX - x0) / frame.width) * 100;
      const dt = ((ev.clientY - y0) / frame.height) * 100;
      onDrag(item.id, +(l0 + dl).toFixed(2), +(t0 + dt).toFixed(2));
    };
    const up = () => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up); };
    window.addEventListener('pointermove', move); window.addEventListener('pointerup', up);
  };
  const startResize = (e) => {
    e.preventDefault(); e.stopPropagation();
    onSelect(item.id);
    const frame = e.currentTarget.closest('.room-frame').getBoundingClientRect();
    const x0 = e.clientX, y0 = e.clientY, w0 = w, h0 = h;
    const move = (ev) => {
      const dw = ((ev.clientX - x0) / frame.width) * 100;
      const dh = ((ev.clientY - y0) / frame.height) * 100;
      onResize(item.id, Math.max(2, +(w0 + dw).toFixed(2)), Math.max(2, +(h0 + dh).toFixed(2)));
    };
    const up = () => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up); };
    window.addEventListener('pointermove', move); window.addEventListener('pointerup', up);
  };

  return (
    <div className={'edit-obj' + (selected ? ' sel' : '')} style={style} onPointerDown={startDrag}>
      {item.src
        ? <img src={srcUrl(item.src)} alt={item.id} draggable="false" />
        : <div className="edit-hotspot"></div>}
      <span className="edit-tag">{item.id}</span>
      <span className="edit-handle" onPointerDown={startResize}></span>
    </div>
  );
}

function EditPanel({ layout, selectedId, onReset }) {
  const fmt = (b) => `[${b.map((n) => (+n).toFixed(1)).join(', ')}]`;
  const copy = () => {
    const obj = {}; layout.forEach((it) => { obj[it.id] = it.box.map((n) => +(+n).toFixed(1)); });
    const text = layout.map((it) => `${it.id}: [${obj[it.id].join(', ')}]`).join('\n');
    navigator.clipboard && navigator.clipboard.writeText(text);
    const btn = document.getElementById('copy-coords-btn');
    if (btn) { btn.textContent = 'Copied ✓'; setTimeout(() => (btn.textContent = 'Copy coords'), 1400); }
  };
  return (
    <div className="edit-panel">
      <div className="ep-head">
        <strong>Position editor</strong>
        <span className="ep-hint">drag to move · corner to resize · ←↑↓→ to nudge · press E to exit</span>
      </div>
      <div className="ep-rows">
        {layout.map((it) => (
          <div key={it.id} className={'ep-row' + (it.id === selectedId ? ' on' : '')}>
            <span className="ep-id">{it.id}</span>
            <span className="ep-box">{fmt(it.box)}</span>
          </div>
        ))}
      </div>
      <div className="ep-actions">
        <button id="copy-coords-btn" onClick={copy}>Copy coords</button>
        <button onClick={onReset}>Reset</button>
      </div>
    </div>
  );
}

function Room({ labelStyle, lampOn, onNavigate, onToggleTheme }) {
  const [layout, setLayout] = React.useState(loadLayout);
  const [edit, setEdit] = React.useState(false);
  const [selectedId, setSelectedId] = React.useState(null);
  const [hoverGroup, setHoverGroup] = React.useState(null);

  // persist
  React.useEffect(() => {
    const obj = {}; layout.forEach((it) => (obj[it.id] = it.box));
    try { localStorage.setItem(LS_KEY, JSON.stringify(obj)); } catch (e) {}
  }, [layout]);

  // toggle edit with "e"; nudge selected with arrows
  React.useEffect(() => {
    const onKey = (e) => {
      const tag = (e.target.tagName || '').toLowerCase();
      if (tag === 'input' || tag === 'textarea') return;
      if (!edit || !selectedId) return;
      const step = e.shiftKey ? 1 : 0.2;
      const d = { ArrowLeft: [-step, 0], ArrowRight: [step, 0], ArrowUp: [0, -step], ArrowDown: [0, step] }[e.key];
      if (!d) return;
      e.preventDefault();
      setLayout((ls) => ls.map((it) => it.id === selectedId
        ? { ...it, box: [+(it.box[0] + d[0]).toFixed(2), +(it.box[1] + d[1]).toFixed(2), it.box[2], it.box[3]] } : it));
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [edit, selectedId]);

  const onDrag = (id, l, t) => setLayout((ls) => ls.map((it) => it.id === id ? { ...it, box: [l, t, it.box[2], it.box[3]] } : it));
  const onResize = (id, w, h) => setLayout((ls) => ls.map((it) => it.id === id ? { ...it, box: [it.box[0], it.box[1], w, h] } : it));
  const onReset = () => { setLayout(DEFAULT_LAYOUT.map((d) => ({ ...d }))); setSelectedId(null); };

  return (
    <div className={'room-frame' + (lampOn ? ' lamp-on' : '') + (edit ? ' editing' : '')}
         data-labels={labelStyle}
         onPointerDown={edit ? () => setSelectedId(null) : undefined}>
      <div className="floor"></div>
      <div className="lamp-glow" style={{ left: '26%', top: '40%', width: '34%', height: '34%' }}></div>

      {edit
        ? layout.map((it) => (
            <EditObject key={it.id} item={it} selected={selectedId === it.id}
              onSelect={setSelectedId} onDrag={onDrag} onResize={onResize} />
          ))
        : layout.map((it) => (
            <LiveObject key={it.id} item={it} onNavigate={onNavigate} onToggleTheme={onToggleTheme}
              hoverGroup={hoverGroup} setHoverGroup={setHoverGroup} />
          ))}
    </div>
  );
}

Object.assign(window, { Room, DEFAULT_LAYOUT });
