/* win95-wizard.jsx — "Windows Chip 95 Setup": the guided-tour wizard.
   Loaded after win95-apps.jsx / win95-extras.jsx (needs PROJECTS, ICON,
   W95Button from the shared script scope), before the inline App script. */

const { useState: useStateW, useEffect: useEffectW, useRef: useRefW } = React;

/* Z layers: dimmed windows (zRef, 11–~1000) < overlay < spotlit windows
   < wizard panel < taskbar (3000) < Assistant (4000) < Dialog (5000). */
const WIZ_OVERLAY_Z = 1200;
const WIZ_WIN_Z = 1300;
const WIZ_PANEL_Z = 2600;
/* Mobile keeps the wizard as a regular floating window above the taskbar. */
const WIZ_MOBILE_Z = 3200;

const WIZ_PROJECT_BLURBS = {
  breathe: 'Wim Hof style cyclic breathing guidance app. Calm is a performance metric.',
  shelf: 'Every book read and every film watched, on one shareable shelf. Taste, version-controlled.',
  tune: 'Name that tune before your friends do. Retro by design, competitive by accident.',
  bday: 'Email birthday reminders. The highest-ROI product in this folder.',
};

/* ---------------- Media: gif → webp → png cascade, icon fallback ------- */
function WizMedia({ base, alt, fallbackIcon, fallbackText, height }) {
  const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const exts = reduced ? ['png', 'webp', 'gif'] : ['gif', 'webp', 'png'];
  const [i, setI] = useStateW(0);
  if (i >= exts.length) {
    return (
      <div className="w95-well" style={{ height, display: 'flex', gap: 12, alignItems: 'center', justifyContent: 'center', padding: 12, boxSizing: 'border-box' }}>
        <img src={ICON(fallbackIcon)} style={{ width: 32, height: 32, imageRendering: 'pixelated', flexShrink: 0 }} alt="" />
        <div style={{ fontSize: 12, lineHeight: 1.5, maxWidth: 320 }}>{fallbackText}</div>
      </div>
    );
  }
  return (
    <div className="w95-sunken" style={{ width: 'fit-content', maxWidth: '100%', margin: '0 auto', overflow: 'hidden', background: '#000' }}>
      <img src={base + '.' + exts[i]} alt={alt} onError={() => setI(i + 1)}
        style={{ width: 'auto', maxWidth: '100%', height, objectFit: 'contain', display: 'block' }} />
    </div>
  );
}

/* ---------------- Step definitions (shared by desktop + mobile) -------- */
/* windows: real WINDOW_DEFS ids opened beside the wizard on desktop.
   x/y are zoomed-local desktop coordinates, clamped at open time. */
const WIZARD_STEPS = [
  {
    id: 'welcome', title: 'Welcome to Setup', art: 'chip-flag-64', assistKey: 'tour-welcome',
    windows: [], isWelcome: true,
    body: ({ next, exit }) => (
      <React.Fragment>
        <p style={{ margin: 0 }}>
          This wizard will take you on a tour of Cip's nostalgic interactive web presence.
        </p>
        <p style={{ margin: '10px 0 0' }}>
          Estimated time: 3 minutes. No restart required.
        </p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 16 }}>
          <W95Button def onClick={next}>Take the tour</W95Button>
          <W95Button onClick={exit}>Explore by yourself</W95Button>
        </div>
      </React.Fragment>
    ),
  },
  {
    id: 'dayjob', title: 'Current role', art: 'user-32', assistKey: 'tour-dayjob',
    windows: [{ id: 'about', x: 610, y: 42 }, { id: 'cv', x: 660, y: 200 }],
    body: ({ openWindow, isMobile }) => (
      <React.Fragment>
        <p style={{ margin: 0 }}>
          Setup has detected a full-time occupation. Cip manages payment authentication at <b>Stripe</b> —
          the invisible "is this really you?" layer protecting a non-trivial chunk of the world's GDP.
        </p>
        <p style={{ margin: '10px 0 0' }}>
          The CV compresses ten years of product work into one .txt file, as nature intended.
        </p>
        {isMobile && (
          <React.Fragment>
            <p style={{ margin: '10px 0 0' }}>
              My CV.txt opens in its own window. Drag its blue title bar to move it around and reveal this wizard again.
            </p>
            <div style={{ marginTop: 10 }}>
              <W95Button onClick={() => openWindow('cv', { x: 12, y: 72, z: WIZ_MOBILE_Z + 100, maximized: false, tourMobile: true })}>
                Open My CV.txt
              </W95Button>
            </div>
          </React.Fragment>
        )}
      </React.Fragment>
    ),
  },
  {
    id: 'projects', title: 'Weekend Projects', art: 'folder-open-32', assistKey: 'tour-projects',
    windows: [{ id: 'projects', x: 640, y: 320 }],
    intro: 'Setup found 4 additional programs installed after hours. All shipped, all live, all built for the fun of it.',
    pages: PROJECTS.map((p) => ({
      projectId: p.id, name: p.name, url: p.url, icon: p.icon,
      media: 'assets/projects/' + p.id,
      blurb: WIZ_PROJECT_BLURBS[p.id] || p.desc,
      desc: p.desc,
    })),
  },
  {
    id: 'recycle', title: 'Quality Control', art: 'recycle-full-32', assistKey: 'tour-recycle',
    windows: [{ id: 'recycle', x: 620, y: 80 }],
    body: () => (
      <React.Fragment>
        <p style={{ margin: 0 }}>
          Not everything ships. The Recycle Bin preserves the ideas that didn't make it —
          blockchain for birthdays, an NFT business plan (v7, FINAL).
        </p>
        <p style={{ margin: '10px 0 0' }}>
          Deleting them was also product work.
        </p>
      </React.Fragment>
    ),
  },
  {
    id: 'taste', title: 'Input Devices', art: 'folder-32', assistKey: 'tour-taste',
    windows: [{ id: 'podcasts', x: 600, y: 40 }, { id: 'blogs', x: 650, y: 240 }],
    body: () => (
      <React.Fragment>
        <p style={{ margin: 0 }}>
          Setup is now installing inputs: the podcasts and newsletters Cip actually reads
          and listens to.
        </p>
      </React.Fragment>
    ),
  },
  {
    id: 'human', title: 'The Human', art: 'earth-32', assistKey: 'tour-human',
    windows: [{ id: 'travel', x: 600, y: 40 }],
    body: () => (
      <React.Fragment>
        <p style={{ margin: 0 }}>
          58 countries visited and counting. Languages installed: English, Italian, Romanian, Spanish.
        </p>
        <p style={{ margin: '10px 0 0' }}>
          The desktop only speaks Win95.
        </p>
      </React.Fragment>
    ),
  },
  {
    id: 'finish', title: 'Setup Complete', art: 'chip-flag-64', assistKey: 'tour-finish',
    windows: [], isFinish: true,
    body: ({ openWindow, exit }) => (
      <React.Fragment>
        <p style={{ margin: 0 }}>
          Windows Chip 95 has been successfully installed. Choose what to launch:
        </p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 12, alignItems: 'stretch' }}>
          <W95Button def onClick={() => window.open('https://www.linkedin.com/in/blujdea', '_blank')}>
            Connect on LinkedIn
          </W95Button>
          <W95Button onClick={() => { exit(); openWindow('mail'); }}>Contact Cip</W95Button>
          <W95Button onClick={exit}>Explore the desktop</W95Button>
        </div>
      </React.Fragment>
    ),
  },
];

/* ---------------- The wizard ------------------------------------------- */
const WIZ_DEFAULT_POS = { x: 48, y: null }; // y: null means "vertically centered"

const MOBILE_WINDOW_PREVIEWS = {
  about: 'Cip Blujdea 95 · Product Builder',
  cv: 'CIPRIAN BLUJDEA — PRODUCT BUILDER',
  projects: '4 after-hours programs installed',
  recycle: 'The ideas that did not make it.',
  podcasts: '4 favorite podcasts',
  blogs: 'A small, well-tended reading list',
  travel: '58 countries visited and counting.',
};

/* On phones, the tour uses these non-interactive window previews so the wizard
   can stay compact while each stop still feels like a real desktop moment. */
function MobileTourWindowPreviews({ windows }) {
  return (
    <div aria-hidden="true" style={{ position: 'absolute', inset: 0, zIndex: WIZ_MOBILE_Z - 1, pointerEvents: 'none' }}>
      {windows.map((w, i) => {
        const def = WINDOW_DEFS[w.id];
        if (!def) return null;
        return (
          <div key={w.id} className="w95-window" style={{
            position: 'absolute', left: 24 + i * 16,
            top: `min(calc(58% + ${i * 18}px), calc(100% - ${188 - i * 12}px))`,
            width: 'calc(100% - 70px)', maxWidth: 300, height: 124,
            display: 'flex', flexDirection: 'column', overflow: 'hidden',
          }}>
            <div className="w95-titlebar">
              <img src={ICON(def.icon)} alt="" />
              <div className="w95-titlebar-title">{def.title}</div>
            </div>
            <div style={{ display: 'flex', gap: 10, alignItems: 'center', padding: 12, fontSize: 11, lineHeight: 1.4 }}>
              <img src={ICON(def.icon)} style={{ width: 32, height: 32, imageRendering: 'pixelated', flexShrink: 0 }} alt="" />
              <span>{MOBILE_WINDOW_PREVIEWS[w.id] || 'Opened by Windows Chip 95 Setup.'}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

function SetupWizard({ isMobile, openWindow, closeWindow, exitTour, assist, wizZRef }) {
  const [step, setStep] = useStateW(0);
  const [page, setPage] = useStateW(0);
  const [pos, setPos] = useStateW(WIZ_DEFAULT_POS);
  const openedRef = useRefW([]);
  const panelRef = useRefW(null);
  const dragRef = useRefW(null);
  const total = WIZARD_STEPS.length;
  const s = WIZARD_STEPS[step];

  const onTitlePointerDown = (e) => {
    if (e.target.closest('.w95-titlebar-btn')) return;
    const el = panelRef.current;
    if (!el) return;
    const parent = el.offsetParent;
    const startLeft = el.offsetLeft;
    /* Before the first drag, top is '46%' + translateY(-50%) — a paint-only transform
       offsetTop doesn't see. Compute the equivalent pixel top by hand so drag doesn't jump. */
    const startTop = pos.y === null
      ? (parent ? parent.clientHeight * 0.46 : window.innerHeight * 0.46) - el.offsetHeight / 2
      : pos.y;
    dragRef.current = { dx: e.clientX - startLeft, dy: e.clientY - startTop };
    const move = (ev) => {
      if (!dragRef.current) return;
      const maxX = (parent ? parent.clientWidth : window.innerWidth) - 60;
      const maxY = (parent ? parent.clientHeight : window.innerHeight) - 30;
      setPos({
        x: Math.max(-el.offsetWidth + 60, Math.min(ev.clientX - dragRef.current.dx, maxX)),
        y: Math.max(0, Math.min(ev.clientY - dragRef.current.dy, maxY)),
      });
    };
    const up = () => {
      dragRef.current = null;
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };

  /* Desktop choreography: swap the real windows each step drives */
  useEffectW(() => {
    if (isMobile) return;
    openedRef.current.forEach((id) => closeWindow(id));
    openedRef.current = [];
    const desk = document.querySelector('[data-screen-label="Desktop"]');
    const deskW = desk ? desk.clientWidth : 1024;
    s.windows.forEach((w) => {
      openWindow(w.id, { x: Math.max(8, Math.min(w.x, deskW - 280)), y: w.y, z: ++wizZRef.current });
      openedRef.current.push(w.id);
    });
    assist(s.assistKey, true);
  }, [step]);

  const exit = () => exitTour();
  const next = () => {
    if (s.pages && page < s.pages.length - 1) { setPage(page + 1); return; }
    if (step < total - 1) { setStep(step + 1); setPage(0); }
    else exit();
  };
  const back = () => {
    if (s.pages && page > 0) { setPage(page - 1); return; }
    if (step > 0) {
      const prev = WIZARD_STEPS[step - 1];
      setStep(step - 1);
      setPage(prev.pages ? prev.pages.length - 1 : 0);
    }
  };

  useEffectW(() => {
    const h = (e) => {
      const tag = (e.target.tagName || '').toLowerCase();
      if (tag === 'input' || tag === 'textarea' || tag === 'select') return;
      if (e.key === 'Enter' || e.key === 'ArrowRight') { e.preventDefault(); next(); }
      else if (e.key === 'ArrowLeft') { e.preventDefault(); back(); }
      else if (e.key === 'Escape') { e.preventDefault(); exit(); }
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [step, page]);

  const atStart = step === 0 && page === 0;
  const nextLabel = s.isFinish ? 'Finish' : 'Next >';

  const pageContent = s.pages && (() => {
    const pg = s.pages[page];
    return (
      <React.Fragment>
        <div style={{ fontSize: 11, color: '#444', marginBottom: 6 }}>
          {s.intro && page === 0 ? s.intro : 'Program ' + (page + 1) + ' of ' + s.pages.length}
        </div>
        <WizMedia key={pg.projectId} base={pg.media} alt={pg.name + ' screenshot'}
          fallbackIcon={pg.icon} fallbackText={pg.desc} height={isMobile ? '34vh' : 170} />
        <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start', marginTop: 10 }}>
          <img src={ICON(pg.icon)} style={{ width: 32, height: 32, imageRendering: 'pixelated', flexShrink: 0 }} alt="" />
          <div style={{ lineHeight: 1.5 }}>
            <b>{pg.name}</b> · <span style={{ fontSize: 11, color: '#444' }}>{page + 1} of {s.pages.length}</span><br />
            {pg.blurb}
          </div>
        </div>
        <div style={{ marginTop: 10 }}>
          <W95Button onClick={() => window.open(pg.url, '_blank')}>Visit site</W95Button>
        </div>
      </React.Fragment>
    );
  })();

  const bodyContent = s.pages ? pageContent : s.body({ openWindow, exit, next, isMobile });

  const footer = (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', borderTop: '1px solid var(--w95-border-dark)', boxShadow: 'inset 0 1px 0 0 var(--w95-border-lightest)' }}>
      <div style={{ fontSize: 11, color: '#444', flexGrow: 1 }}>Step {step + 1} of {total}</div>
      <W95Button style={{ minWidth: 76 }} disabled={atStart} onClick={back}>{'< Back'}</W95Button>
      {!s.isWelcome && <W95Button def style={{ minWidth: 76 }} onClick={next}>{nextLabel}</W95Button>}
      <W95Button style={{ minWidth: 76 }} onClick={exit}>Cancel</W95Button>
    </div>
  );

  if (isMobile) {
    const onPointerDown = (e) => {
      if (e.target.closest('.w95-titlebar-btn')) return;
      const el = e.currentTarget.parentElement;
      dragRef.current = { dx: e.clientX - el.offsetLeft, dy: e.clientY - el.offsetTop };
      const move = (ev) => {
        if (!dragRef.current) return;
        const root = el.parentElement;
        const x = Math.max(0, Math.min(ev.clientX - dragRef.current.dx, root.clientWidth - el.offsetWidth));
        const y = Math.max(0, Math.min(ev.clientY - dragRef.current.dy, root.clientHeight - el.offsetHeight - 36));
        el.style.left = x + 'px';
        el.style.top = y + 'px';
      };
      const up = () => {
        dragRef.current = null;
        window.removeEventListener('pointermove', move);
        window.removeEventListener('pointerup', up);
      };
      window.addEventListener('pointermove', move);
      window.addEventListener('pointerup', up);
    };
    return (
      <React.Fragment>
        <MobileTourWindowPreviews windows={s.windows} />
        <div data-screen-label="Setup wizard" className="w95-window" style={{ position: 'absolute', left: 12, top: 12, zIndex: WIZ_MOBILE_Z, display: 'flex', flexDirection: 'column', width: 'calc(100% - 24px)', maxWidth: s.pages ? 320 : 360, maxHeight: 'calc(100% - 48px)' }}>
          <div className="w95-titlebar" onPointerDown={onPointerDown} style={{ touchAction: 'none', cursor: 'move' }}>
            <img src={ICON('chip-flag')} alt="" />
            <div className="w95-titlebar-title">Windows Chip 95 Setup</div>
            <div className="w95-titlebar-options">
              <button className="w95-btn w95-titlebar-btn" aria-label="Close" onClick={exit}>✕</button>
            </div>
          </div>
          <div style={{ height: 48, background: 'linear-gradient(90deg, #00007f, #1084d0)', display: 'flex', alignItems: 'center', gap: 12, padding: '0 14px', flexShrink: 0 }}>
            <img src={ICON(s.art)} style={{ width: 32, height: 32, imageRendering: 'pixelated' }} alt="" />
            <div style={{ color: '#fff', fontWeight: 'bold', fontSize: 15 }}>{s.title}</div>
          </div>
          <div className="w95-scroll" style={{ flexGrow: 1, overflowY: 'auto', padding: 14, fontSize: 13, lineHeight: 1.5 }}>
            {bodyContent}
          </div>
          {footer}
        </div>
      </React.Fragment>
    );
  }

  const posStyle = pos.y === null
    ? { left: pos.x, top: '46%', transform: 'translateY(-50%)' }
    : { left: pos.x, top: pos.y };

  return (
    <div ref={panelRef} data-screen-label="Setup wizard"
      style={{ position: 'absolute', ...posStyle, zIndex: WIZ_PANEL_Z, width: s.pages ? 'min(340px, calc(100% - 24px))' : 'min(540px, calc(100% - 64px))' }}>
      <div className="w95-window">
        <div className="w95-titlebar" onPointerDown={onTitlePointerDown} style={{ touchAction: 'none' }}>
          <img src={ICON('chip-flag')} alt="" />
          <div className="w95-titlebar-title">Windows Chip 95 Setup</div>
          <div className="w95-titlebar-options">
            <button className="w95-btn w95-titlebar-btn" aria-label="Close" onClick={exit}>✕</button>
          </div>
        </div>
        <div style={{ display: 'flex', minHeight: 260 }}>
          <div style={{ width: 96, flexShrink: 0, background: 'linear-gradient(180deg, #00007f, #000e7a 60%, #1084d0)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <img src={ICON(s.art)} style={{ width: 48, height: 48, imageRendering: 'pixelated' }} alt="" />
          </div>
          <div style={{ padding: '14px 16px', flexGrow: 1, fontSize: 12, lineHeight: 1.5, minWidth: 0 }}>
            <div style={{ fontSize: 16, fontWeight: 'bold', marginBottom: 10 }}>{s.title}</div>
            {bodyContent}
          </div>
        </div>
        {footer}
      </div>
    </div>
  );
}

Object.assign(window, { SetupWizard, WIZARD_STEPS, WIZ_OVERLAY_Z, WIZ_WIN_Z, WIZ_PANEL_Z, WIZ_MOBILE_Z });
