// Main App — editorial grid index; click card → modal (iframe if live, else screenshot + brief).

const { useState, useEffect, useCallback } = React;

const DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "ivory",
  "accent": "#4a1d96",
  "showDates": true,
  "framing": "museum"
} /*EDITMODE-END*/;

const Header = () =>
<header className="site-head">
    <div className="site-head-l">
      <div className="site-mark">Y.</div>
      <div>
        <div className="site-name">Yang · <i>AI Portfolio</i></div>
        <div className="site-kicker">PROOFS OF CONCEPT · 2025–2026 · NYU LANGONE HEALTH</div>
      </div>
    </div>
    <div className="site-head-r">
      <span className="site-meta">COLLECTION № 01</span>
      <span className="site-meta">09 ARTIFACTS</span>
      <span className="site-meta dot">ON VIEW · 2</span>
    </div>
  </header>;



/* ─────────── Shot: real screenshot, or typographic placeholder ─────────── */
const Shot = ({ p, className = '' }) => {
  if (p.shot) {
    return <img className={`shot-img ${className}`} src={p.shot} alt={p.title} loading="lazy" />;
  }
  return (
    <div className={`shot-placeholder ${className}`} style={{ '--accent': p.accent }}>
      <div className="sp-num">{p.num}</div>
      <div className="sp-title">{p.title}</div>
    </div>
  );
};

/* ─────────── Card ─────────── */
const ProjectCard = ({ p, onOpen }) => {
  const isLive = p.status === 'active';
  return (
    <article className="card" style={{ '--accent': p.accent }}>
      <button className="card-thumb" onClick={() => onOpen(p.id)} aria-label={`Preview ${p.title}`}>
        <Shot p={p} />
        <div className="card-thumb-overlay">
          <span className="card-thumb-cta">
            {isLive ? 'Launch live preview' : 'Open preview'}
            <span className="arrow">→</span>
          </span>
        </div>
      </button>
      <div className="card-meta">
        <div className="card-index">
          <span className="num">{p.num}.</span>
          {isLive && (
            <span className="card-status live">
              <span className="status-dot" /> {p.statusLabel}
            </span>
          )}
        </div>
        <h3 className="card-title">{p.title}</h3>
        <p className="card-sub">{p.subtitle}</p>
      </div>
    </article>
  );
};

/* ─────────── Modal ─────────── */
const Modal = ({ p, onClose, onMinimize }) => {
  const [iframeLoaded, setIframeLoaded] = useState(false);
  const canEmbed = p.liveUrl && p.embeddable && window.innerWidth > 768;

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [onClose]);

  const isExternal = typeof p.liveUrl === 'string' && /^https?:\/\//.test(p.liveUrl);
  const host = isExternal ? new URL(p.liveUrl).host : null;

  return (
    <div className="modal-root" role="dialog" aria-modal="true" aria-label={p.title}>
      <div className="modal-scrim" onClick={onClose} />
      <div className="modal-frame" style={{ '--accent': p.accent }}>
        <div className="modal-bar">
          <div className="modal-bar-l">
            <span className="modal-num">{p.num}.</span>
            <span className="modal-title">{p.title}</span>
            {host && (
              <a className="modal-url" href={p.liveUrl} target="_blank" rel="noopener">
                {host}
                <span className="modal-url-arrow">↗</span>
              </a>
            )}
          </div>
          <div className="modal-bar-r">
            {p.liveUrl && (
              <a className="modal-ctrl" href={p.liveUrl} target="_blank" rel="noopener" title="Open in new tab">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                  <path d="M7 17L17 7M17 7H9M17 7V15" />
                </svg>
              </a>
            )}
            <button className="modal-ctrl" onClick={onMinimize} title="Minimize">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M5 19H19" />
              </svg>
            </button>
            <button className="modal-ctrl modal-close" onClick={onClose} title="Close">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M6 6L18 18M6 18L18 6" />
              </svg>
            </button>
          </div>
        </div>

        <div className="modal-body">
          {canEmbed ? (
            <div className="modal-iframe-wrap">
              {!iframeLoaded && (
                <div className="modal-iframe-loading">
                  <div className="loader-dots"><i /><i /><i /></div>
                  <div className="loader-label">Loading live preview · {host}</div>
                </div>
              )}
              <iframe
                className="modal-iframe"
                src={p.liveUrl}
                title={p.title}
                onLoad={() => setIframeLoaded(true)}
                sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-modals"
                allow="camera; microphone; clipboard-read; clipboard-write; autoplay; display-capture; fullscreen"
                referrerPolicy="no-referrer-when-downgrade"
              />
            </div>
          ) : (
            <div className="modal-brief">
              <div className="modal-brief-img">
                <Shot p={p} className="shot-img--large" />
              </div>
              <div className="modal-brief-text">
                <div className="detail-kicker">BRIEF</div>
                <div className="detail-tagline"><i>{p.tagline}</i></div>
                <div className="detail-block">
                  <div className="detail-block-h">Situation</div>
                  <p>{p.situation}</p>
                </div>
                <div className="detail-block">
                  <div className="detail-block-h">Action</div>
                  <p>{p.action}</p>
                </div>
                <div className="detail-block">
                  <div className="detail-block-h">Result</div>
                  <p>{p.result}</p>
                </div>
                {p.liveUrl && (
                  <a className="modal-openout" href={p.liveUrl} target="_blank" rel="noopener">
                    Open in new tab ↗
                  </a>
                )}
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

/* ─────────── Minimized dock ─────────── */
const MinimizedDock = ({ items, onRestore, onClose }) => {
  if (!items.length) return null;
  return (
    <div className="dock">
      {items.map((p) => (
        <div key={p.id} className="dock-pill" style={{ '--accent': p.accent }}>
          <button className="dock-pill-body" onClick={() => onRestore(p.id)} title={`Restore ${p.title}`}>
            <span className="dock-pill-num">{p.num}.</span>
            <span className="dock-pill-title">{p.title}</span>
          </button>
          <button className="dock-pill-close" onClick={() => onClose(p.id)} title="Close">×</button>
        </div>
      ))}
    </div>
  );
};

/* ─────────── Index ─────────── */
const Index = ({ onOpen }) =>
<section className="index">
    <div className="index-head">
      <div className="index-kicker">THE COLLECTION</div>
      <div className="index-head-r">
        <h2 className="index-h">Proof of Concepts</h2>
        <p className="index-sub">Early demos — intended to be shown with the assistance of the creator.</p>
      </div>
    </div>
    <div className="cards">
      {window.PROJECTS.map((p) => <ProjectCard key={p.id} p={p} onOpen={onOpen} />)}
    </div>
  </section>;

const Foot = () =>
<footer className="site-foot">
    <div className="foot-grid">
      <div>
        <div className="foot-kicker">PROVENANCE</div>
        <p>All works produced at NYU Langone Health. Every project in this collection performs inference against the internal HIPAA-compliant UltraViolet gateway; no regulated data is sent to external providers at any stage.</p>
      </div>
      <div></div>
      <div>
        <div className="foot-kicker">CONTACT</div>
        <p>For a live walkthrough of Frontier AI, or to revisit any retired work, reach out internally.</p>
        <div className="foot-sig">— Y.</div>
      </div>
    </div>
    <div className="foot-rule" />
    <div className="foot-bottom">YANG · AI PORTFOLIO · MMXXVI</div>
  </footer>;

/* ─────────── Tweaks ─────────── */
const Tweaks = ({ open, state, setState, onClose }) => {
  if (!open) return null;
  return (
    <div className="tweaks">
      <div className="tweaks-h">
        <b>Tweaks</b>
        <span className="tw-close" onClick={onClose}>×</span>
      </div>
      <div className="tw-row">
        <label>Theme</label>
        <div className="tw-opts">
          {['ivory', 'parchment', 'dusk'].map((t) =>
          <button key={t} className={state.theme === t ? 'on' : ''} onClick={() => setState({ theme: t })}>{t}</button>
          )}
        </div>
      </div>
      <div className="tw-row">
        <label>Accent</label>
        <div className="tw-opts">
          {[['#4a1d96', 'violet'], ['#b45309', 'amber'], ['#0f766e', 'teal'], ['#0a0a0a', 'ink']].map(([c, n]) =>
          <button key={c} className={state.accent === c ? 'on' : ''} style={{ background: c, color: '#fff' }} onClick={() => setState({ accent: c })}>{n}</button>
          )}
        </div>
      </div>
      <div className="tw-row">
        <label>Framing</label>
        <div className="tw-opts">
          {[['museum', 'Museum catalogue'], ['brief', 'Executive brief']].map(([v, n]) =>
          <button key={v} className={state.framing === v ? 'on' : ''} onClick={() => setState({ framing: v })}>{n}</button>
          )}
        </div>
      </div>
      <div className="tw-row">
        <label>Dates</label>
        <div className="tw-opts">
          <button className={state.showDates ? 'on' : ''} onClick={() => setState({ showDates: true })}>Show</button>
          <button className={!state.showDates ? 'on' : ''} onClick={() => setState({ showDates: false })}>Hide</button>
        </div>
      </div>
    </div>);

};

/* ─────────── App ─────────── */
const App = () => {
  const [tweaks, setTweaks] = useState(() => ({ ...DEFAULTS, ...JSON.parse(localStorage.getItem('tweaks') || '{}') }));
  const [tweaksOpen, setTweaksOpen] = useState(false);
  const [activeId, setActiveId] = useState(null);
  const [minimizedIds, setMinimizedIds] = useState([]);

  useEffect(() => {
    localStorage.setItem('tweaks', JSON.stringify(tweaks));
    document.documentElement.dataset.theme = tweaks.theme;
    document.documentElement.dataset.framing = tweaks.framing;
    document.documentElement.dataset.showdates = tweaks.showDates;
    document.documentElement.style.setProperty('--brand', tweaks.accent);
  }, [tweaks]);

  useEffect(() => {
    const onMsg = (e) => {
      if (e.data?.type === '__activate_edit_mode') setTweaksOpen(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);

  const update = (patch) => {
    setTweaks((s) => {
      const next = { ...s, ...patch };
      window.parent.postMessage({ type: '__edit_mode_set_keys', edits: patch }, '*');
      return next;
    });
  };

  const openProject = useCallback((id) => {
    setMinimizedIds((ids) => ids.filter((x) => x !== id));
    setActiveId(id);
  }, []);

  const closeProject = useCallback(() => setActiveId(null), []);

  const minimizeProject = useCallback(() => {
    setActiveId((cur) => {
      if (cur) setMinimizedIds((ids) => (ids.includes(cur) ? ids : [...ids, cur]));
      return null;
    });
  }, []);

  const closeFromDock = useCallback((id) => {
    setMinimizedIds((ids) => ids.filter((x) => x !== id));
  }, []);

  const activeProject = activeId ? window.PROJECTS.find((p) => p.id === activeId) : null;
  const minimizedProjects = minimizedIds.map((id) => window.PROJECTS.find((p) => p.id === id)).filter(Boolean);

  return (
    <div className="site">
      <Header />
      <Index onOpen={openProject} />
      <Foot />
      {activeProject && (
        <Modal p={activeProject} onClose={closeProject} onMinimize={minimizeProject} />
      )}
      <MinimizedDock items={minimizedProjects} onRestore={openProject} onClose={closeFromDock} />
      <Tweaks open={tweaksOpen} state={tweaks} setState={update} onClose={() => setTweaksOpen(false)} />
    </div>);

};

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
