/* app.jsx — HYPT Web Redesign Prototype
   Home page · 3 interaction states:
     State 1 — Hero (기본)
     State 2 — Index Open (swipe up)
     State 3 — Index Item Hover (blur band + sequential typewriter + CTA slide-in)
*/

// ─────────────────────────────────────────
// HOOKS
// ─────────────────────────────────────────

function useSubhead() {
  const [now,     setNow]     = React.useState(new Date());
  const [colonOn, setColonOn] = React.useState(true);
  React.useEffect(() => {
    const id = setInterval(() => {
      setNow(new Date());
      setColonOn(v => !v);
    }, 1000);
    return () => clearInterval(id);
  }, []);
  const parts = tz => new Intl.DateTimeFormat('en-GB', {
    hour: '2-digit', minute: '2-digit', hour12: false, timeZone: tz,
  }).format(now).split(':');
  return { seoul: parts('Asia/Seoul'), la: parts('America/Los_Angeles'), colonOn };
}

// ─────────────────────────────────────────
// COMPONENTS
// ─────────────────────────────────────────

// onLeave is intentionally absent — hover clearing is handled at the
// list-container level so row-to-row transitions never pass through null.
function IndexRow({ item, hovered, onEnter }) {
  const totalChars = item.name.length + item.desc.length;
  const SPEED      = 10;

  const [stage,      setStage]      = React.useState('idle');
  const [nameTxt,    setNameTxt]    = React.useState(item.name);
  const [descTxt,    setDescTxt]    = React.useState(item.desc);
  const [numTxt,     setNumTxt]     = React.useState(item.date);
  const [ctaVis,     setCtaVis]     = React.useState(false);
  const [typedChars, setTypedChars] = React.useState(0);

  React.useEffect(() => {
    if (!hovered) {
      setNameTxt(item.name);
      setDescTxt(item.desc);
      setNumTxt(item.date);
      setCtaVis(false);
      setTypedChars(0);
      setStage('idle');
      return;
    }
    setNameTxt('');
    setDescTxt('');
    setNumTxt('');
    setCtaVis(false);
    setTypedChars(0);
    setStage('name');
  }, [hovered]);

  // Stage 1: type name, track progress
  React.useEffect(() => {
    if (stage !== 'name') return;
    let i = 0;
    const id = setInterval(() => {
      i++;
      setNameTxt(item.name.slice(0, i));
      setTypedChars(i);
      if (i >= item.name.length) { clearInterval(id); setStage('desc'); }
    }, SPEED);
    return () => clearInterval(id);
  }, [stage]);

  // Stage 2: type desc, continue progress, then trigger CTA
  React.useEffect(() => {
    if (stage !== 'desc') return;
    const nameLen = item.name.length;
    let i = 0;
    const id = setInterval(() => {
      i++;
      setDescTxt(item.desc.slice(0, i));
      setTypedChars(nameLen + i);
      if (i >= item.desc.length) {
        clearInterval(id);
        setNumTxt(item.date);
        setCtaVis(true);
        setStage('done');
      }
    }, SPEED);
    return () => clearInterval(id);
  }, [stage]);

  // Band background clip: reveals left→right in sync with typewriter
  const rightClip = hovered
    ? ((1 - typedChars / totalChars) * 100).toFixed(1)
    : 100;

  return (
    <div className="index-row">
      <div className="index-row__band" onMouseEnter={onEnter}>
        {hovered && (
          <div
            className="index-row__band-bg"
            style={{ clipPath: `inset(0 ${rightClip}% 0 0)` }}
          />
        )}
        <span className="index-row__name">{nameTxt}</span>
        <span className="index-row__desc">{descTxt}</span>
        <span className="index-row__num">{numTxt}</span>
      </div>
      <button className="index-row__cta" onClick={() => { window.location.href = 'work-detail.html'; }}>
        <span className={`index-row__cta-inner${ctaVis ? ' index-row__cta-inner--visible' : ''}`}>
          ( <span className="btn-label">SEE DETAIL →</span> )
        </span>
      </button>
    </div>
  );
}

// ─────────────────────────────────────────
// APP
// ─────────────────────────────────────────

function App() {
  const [indexOpen, setIndexOpen] = React.useState(false);
  const [hoveredId, setHoveredId] = React.useState(null);
  const videoRef  = React.useRef(null);
  const panelRef  = React.useRef(null);

  // Derive flat index items from CMS project/asset structure
  const items = DATA.projects.map(p => {
    const main = p.assets.find(a => a.isMain) || p.assets[0];
    return { id: p.id, name: p.name, desc: p.desc, date: p.date, thumb: main?.src || '' };
  });

  const { seoul, la, colonOn } = useSubhead();
  useHlsVideo(videoRef, DATA.videoSrc, DATA.videoFallback);

  React.useEffect(() => {
    if (indexOpen) return;
    const handler = (e) => { if (e.deltaY > 0) setIndexOpen(true); };
    window.addEventListener('wheel', handler, { passive: true });
    return () => window.removeEventListener('wheel', handler);
  }, [indexOpen]);

  // Compute panel height = ctrlH + n×rowH + rowH/2
  // so the last visible row is always half-clipped (scroll cue).
  // Targets ~50vh; recalculates on every window resize.
  React.useEffect(() => {
    const adjust = () => {
      const panel = panelRef.current;
      if (!panel) return;
      const ctrl     = panel.querySelector('.index-panel__ctrl');
      const firstRow = panel.querySelector('.index-row');
      if (!ctrl || !firstRow) return;
      const ctrlH = ctrl.getBoundingClientRect().height;
      const rowH  = firstRow.getBoundingClientRect().height;
      if (!ctrlH || !rowH) return;
      const targetListH = window.innerHeight / 2 - ctrlH;
      const n = Math.max(0, Math.floor((targetListH - rowH / 2) / rowH));
      panel.style.height = `${ctrlH + n * rowH + rowH / 2}px`;
    };
    adjust();
    window.addEventListener('resize', adjust);
    return () => window.removeEventListener('resize', adjust);
  }, []);

  function closeIndex() {
    setIndexOpen(false);
    setHoveredId(null);
  }

  const hoveredItem = items.find((it) => it.id === hoveredId) || null;

  return (
    <div className="hero">

      <div className="hero__video-wrap">
        <video ref={videoRef} autoPlay muted loop playsInline />
      </div>

      {hoveredItem && (
        <div
          className="hero__thumb"
          style={{ backgroundImage: `url(${hoveredItem.thumb})` }}
        />
      )}

      <div className="hero__overlay" />
      <VerticalGuides />

      <div className="hero__top">
        <HeroGNB activePage={null} onLogoClick={closeIndex} />
        <div className="hero__subhead-row">
          <span className="hero__subhead">
            HUMAN X AGENTIC BRANDING ･ SEOUL {seoul[0]}<span className={colonOn ? '' : 'hero__colon--off'}>:</span>{seoul[1]} ･ LOS ANGELES {la[0]}<span className={colonOn ? '' : 'hero__colon--off'}>:</span>{la[1]}
          </span>
        </div>
      </div>

      <div ref={panelRef} className={`index-panel${indexOpen ? ' index-panel--open' : ''}`}>
        <div className="index-panel__ctrl">
          {indexOpen ? (
            <Btn onClick={closeIndex}>HIDE INDEX ↓</Btn>
          ) : (
            <Btn onClick={() => setIndexOpen(true)}>OPEN INDEX ↑</Btn>
          )}
        </div>

        {/*
          onMouseLeave on the LIST, not on individual rows.
          When moving between rows, the list never fires mouseleave
          so hoveredId never passes through null → no thumbnail flicker.
          hoveredId clears only when mouse exits the list entirely.
        */}
        <div
          className="index-panel__list"
          onMouseLeave={() => setHoveredId(null)}
        >
          {items.map((item) => (
            <IndexRow
              key={item.id}
              item={item}
              hovered={hoveredId === item.id}
              onEnter={() => setHoveredId(item.id)}
            />
          ))}
          <div className="index-panel__footer">© 2026 HYPT</div>
        </div>
      </div>

    </div>
  );
}

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