// Guided walkthrough - spotlights each UI element in turn with a floating
// tooltip. The customer drives every interaction: the tour never clicks
// buttons or navigates screens on their behalf. Action steps wait for the
// user's click before advancing; nav steps auto-advance when the expected
// screen appears.
//
// Step fields:
//   screen:           which route this step belongs to (or 'any')
//   target:           CSS selector for the element to spotlight (or null = centered)
//   title, body:      copy (body may be a function(ctx) => string)
//   placement:        tooltip position relative to target
//   waitForClick:     boolean - disable Next, advance when target is clicked
//   advanceOnScreen:  auto-advance when state.screen becomes this value
//   cta:              override Next-button label

const TOUR_STEPS = [
  // ==== Pipeline ====
  {
    screen: 'pipeline', target: null,
    title: 'Let me walk you through this.',
    body: ({ prospect }) =>
      `Hi ${prospect.firstName || prospect.business}. Quick 60-second tour of the whole app - pipeline, AI quote generator, invoicing. You'll be clicking through it yourself, I\u2019ll just point at things.`,
    cta: 'Start the tour \u2192',
    placement: 'center',
  },
  {
    screen: 'pipeline', target: '[data-tour="kpis"]',
    title: 'Your business at a glance.',
    body: () => 'Pipeline value, approved-this-month, cash owed, overdue. Updated live from every action below - no dashboards to build.',
    placement: 'bottom',
  },
  {
    screen: 'pipeline', target: '[data-tour="board"]',
    title: 'The pipeline itself.',
    body: () => 'Every job in your shop lives on this board. Eight stages, left to right: enquiry \u2192 site visit \u2192 quoting \u2192 approved \u2192 scheduled \u2192 in progress \u2192 invoiced \u2192 paid.',
    placement: 'top',
  },
  {
    screen: 'pipeline', target: '[data-tour="stage-enquiry"]',
    title: 'New enquiries land here first.',
    body: () => 'Phone call, web form, Facebook DM - all routed into this column. Coldest on top. Hot ones get a flag.',
    placement: 'right',
  },
  {
    screen: 'pipeline', target: '[data-tour="hot-card"]',
    title: "Today\u2019s hot enquiry.",
    body: () => 'Your tech\u2019s already been on-site and uploaded 4 photos + a voice note. That\u2019s the interesting bit - we\u2019ll open this job next.',
    placement: 'right',
  },
  {
    screen: 'pipeline', target: '[data-tour="stage-quoting"]',
    title: 'Mid-funnel: waiting on the customer.',
    body: () => 'Quote\u2019s been drafted, sent to the customer, and is sitting on their phone. The small orange dot means AI drafted this one.',
    placement: 'left',
  },
  {
    screen: 'pipeline', target: '[data-tour="stage-paid"]',
    title: 'End of the line: paid.',
    body: () => 'PayID link went out, customer tapped it, money hit your account. Shows up here automatically - no chasing, no reconciling.',
    placement: 'left',
  },
  // ==== Field-tech mobile (where the data comes from) ====
  {
    screen: 'pipeline', target: '[data-tour="nav-field-tech"]',
    title: 'But before any of this - the tradie\u2019s side.',
    body: () => 'Enquiries don\u2019t appear out of thin air. Your tech captures everything on-site, on their phone. Click "Field tech (mobile)" in the sidebar to see how.',
    placement: 'right',
    waitForClick: true,
    advanceOnScreen: 'field-tech',
  },
  {
    screen: 'field-tech', target: '[data-tour="iphone-frame"]',
    title: 'Same app, on the phone.',
    body: () => 'Today\u2019s stops on top, job brief in the middle, capture flow at the bottom (photos + voice note + typed notes). When the tech hits Done at the end of capture, everything pushes back to the office pipeline - and the AI starts drafting the quote in the background.',
    placement: 'left',
  },
  {
    screen: 'field-tech', target: '[data-tour="nav-pipeline"]',
    title: 'Now back to the office.',
    body: () => 'Click Pipeline in the sidebar. We\u2019ll open the AI quote generator and watch it work on the data your tech just captured.',
    placement: 'right',
    waitForClick: true,
    advanceOnScreen: 'pipeline',
  },
  {
    screen: 'pipeline', target: '[data-tour="new-job"]',
    title: 'Open the AI quote generator.',
    body: () => 'Click the orange New job button up top. We\u2019ll look at the quote the AI drafted from those photos + voice note.',
    placement: 'bottom',
    waitForClick: true,
    advanceOnScreen: 'ai-quote',
  },

  // ==== AI Quote ====
  {
    screen: 'ai-quote', target: '[data-tour="photos"]',
    title: 'Every photo your tech took.',
    body: () => '4 photos from the site visit - living-room wall, outdoor yard, switchboard, pipe-run under the eaves. Each has a caption the tech added in the van.',
    placement: 'right',
  },
  {
    screen: 'ai-quote', target: '[data-tour="voice"]',
    title: 'Plus a voice note.',
    body: () => '2 minutes of your tech rambling through what they saw - auto-transcribed, included as AI input. No more illegible notebook pages.',
    placement: 'right',
  },
  {
    screen: 'ai-quote', target: '[data-tour="generate"]',
    title: 'Hit Generate yourself.',
    body: () => 'Click the Generate with AI button. Line items will stream in on the right one-by-one, and partway through it\u2019ll pause to ask you a clarifying question.',
    placement: 'right',
    waitForClick: true,
  },
  {
    screen: 'ai-quote', target: '[data-tour="status"]',
    title: "It\u2019s working now.",
    body: () => 'Reading photos, classifying the job (\u201CHVAC install, single-room, residential\u201D), drafting line items, reconciling GST. All visible as it happens - no black box.',
    placement: 'bottom',
  },
  {
    screen: 'ai-quote', target: '[data-tour="items"]',
    title: 'Line items stream in.',
    body: () => 'Parts, labour, compliance, disposal - all priced at your rates. Each line editable: qty, rate, note. Remove any line you don\u2019t want with the \u00d7.',
    placement: 'left',
  },
  {
    screen: 'ai-quote', target: '[data-tour="clarify"]',
    title: 'Smart clarifying question.',
    body: () => 'Mid-stream the AI pauses to ask the one thing it can\u2019t know - asbestos risk on pre-1980 homes, STC zone for solar, heritage rules for electrical. Click Yes or Skip yourself to answer it.',
    placement: 'top',
    waitForClick: true,
  },
  {
    screen: 'ai-quote', target: '[data-tour="totals"]',
    title: 'GST and total - live.',
    body: () => 'Subtotal ex-GST, 10% GST, total inc-GST. Tallies live as lines arrive and as you edit. Australian-compliant, no spreadsheet needed.',
    placement: 'left',
  },
  {
    screen: 'ai-quote', target: '[data-tour="send"]',
    title: 'Send it to the customer.',
    body: () => 'Click the green Send button. The customer gets an SMS with a link - no signup, no login, no app to install.',
    placement: 'top',
    waitForClick: true,
    advanceOnScreen: 'customer-approval',
  },

  // ==== Customer approval ====
  {
    screen: 'customer-approval', target: '[data-tour="approval-card"]',
    title: 'This is what your customer sees.',
    body: () => 'Same page on their phone after they tap the SMS link. Clean breakdown, no jargon, your branding, their job\u2019s details. Notice the URL up top - a signed share link, no account required.',
    placement: 'left',
  },
  {
    screen: 'customer-approval', target: '[data-tour="approve-btn"]',
    title: 'They tap Approve.',
    body: () => 'Tap it yourself to play the customer. Approval is logged with timestamp + IP - legal-grade audit trail, no DocuSign needed.',
    placement: 'top',
    waitForClick: true,
  },
  {
    screen: 'customer-approval', target: '[data-tour="see-invoice-btn"]',
    title: 'Approved - quote becomes a job.',
    body: () => 'Your admin gets pinged immediately. The job moves into Scheduled on your pipeline board automatically. Now click "See the invoice" to see how this turns into money.',
    placement: 'top',
    waitForClick: true,
    advanceOnScreen: 'invoice',
  },

  // ==== Invoice + payment ====
  {
    screen: 'invoice', target: '[data-tour="invoice-doc"]',
    title: 'Tax invoice - auto-generated.',
    body: () => 'Same line items as the approved quote, GST itemized, your ABN, your branding, due date 14 days out. No re-typing, no copy-paste, no spreadsheet.',
    placement: 'right',
  },
  {
    screen: 'invoice', target: '[data-tour="payment-options"]',
    title: 'Three ways to get paid.',
    body: () => 'PayID (instant, free), BPAY (overnight, free), or card via Stripe (1.4% surcharge). Customer picks. Most pick PayID.',
    placement: 'top',
  },
  {
    screen: 'invoice', target: '[data-tour="pay-btn"]',
    title: 'When the money lands, tap here.',
    body: () => 'Click Mark as paid yourself - the balance drops to zero, the job moves to the Paid column, Xero gets the entry pushed. Your job here is done.',
    placement: 'left',
    waitForClick: true,
  },

  // ==== Wrap ====
  {
    screen: 'any', target: null,
    title: 'Loop closed.',
    body: () =>
      'Tech captures on-site \u2192 AI drafts the quote \u2192 you send \u2192 customer approves on their phone \u2192 invoice goes out \u2192 PayID lands the money \u2192 Xero is updated \u2192 the job sits in Paid. The rest of the sidebar (Schedule, Settings, Onboarding, Capabilities) all work too - click around, nothing\u2019s locked.',
    cta: 'Finish tour',
    placement: 'center',
  },
];

function Tour({ state, setState, prospect }) {
  const LS_KEY = `tradesflow-tour:${prospect.slug}`;

  const [step, setStep] = React.useState(() => {
    try { return localStorage.getItem(LS_KEY) === 'done' ? -1 : 0; } catch { return 0; }
  });
  const [rect, setRect] = React.useState(null);
  const [tick, setTick] = React.useState(0);

  const s = step >= 0 ? TOUR_STEPS[step] : null;
  const onRightScreen = s && (s.screen === 'any' || s.screen === state.screen);

  // Measure target element - re-measure on step change, screen change, resize, scroll.
  React.useEffect(() => {
    if (!s || !onRightScreen) return;
    const measure = () => {
      if (!s.target) { setRect(null); return; }
      const el = document.querySelector(s.target);
      if (!el) { setRect(null); return; }
      el.scrollIntoView({ block: 'center', behavior: 'smooth', inline: 'nearest' });
      setTimeout(() => {
        const r = el.getBoundingClientRect();
        setRect({ top: r.top, left: r.left, width: r.width, height: r.height });
      }, 320);
    };
    measure();
    const onResize = () => setTick(t => t + 1);
    window.addEventListener('resize', onResize);
    window.addEventListener('scroll', onResize, true);
    return () => {
      window.removeEventListener('resize', onResize);
      window.removeEventListener('scroll', onResize, true);
    };
  }, [step, state.screen, tick, onRightScreen]);

  // While streaming on ai-quote, the DOM changes - re-measure periodically.
  React.useEffect(() => {
    if (state.screen !== 'ai-quote' || !s) return;
    const id = setInterval(() => setTick(t => t + 1), 500);
    return () => clearInterval(id);
  }, [state.screen, step]);

  // waitForClick: attach a click listener to the target; advance on fire.
  // Skipped when advanceOnScreen is also set - the screen-change handler is
  // the truer signal there, and firing both races the step counter past one.
  React.useEffect(() => {
    if (!s || !s.waitForClick || !s.target || !onRightScreen) return;
    if (s.advanceOnScreen) return;
    let el = document.querySelector(s.target);
    if (!el) {
      const t = setTimeout(() => setTick(x => x + 1), 300);
      return () => clearTimeout(t);
    }
    const startedAt = step;
    const handler = () => {
      setTimeout(() => setStep(cur => cur === startedAt ? cur + 1 : cur), 550);
    };
    el.addEventListener('click', handler);
    return () => el.removeEventListener('click', handler);
  }, [step, tick, onRightScreen]);

  // advanceOnScreen: auto-advance once the expected screen appears.
  React.useEffect(() => {
    if (!s || !s.advanceOnScreen) return;
    if (state.screen === s.advanceOnScreen && step < TOUR_STEPS.length - 1) {
      const nextIdx = TOUR_STEPS.findIndex((st, i) => i > step && (st.screen === state.screen || st.screen === 'any'));
      if (nextIdx > step) {
        const t = setTimeout(() => setStep(nextIdx), 350);
        return () => clearTimeout(t);
      }
    }
  }, [state.screen, step]);

  if (!s) return null;
  if (!onRightScreen) return null;

  const dismiss = () => {
    try { localStorage.setItem(LS_KEY, 'done'); } catch {}
    setStep(-1);
  };

  const next = () => {
    if (step >= TOUR_STEPS.length - 1) { dismiss(); return; }
    setStep(step + 1);
  };
  const back = () => setStep(Math.max(0, step - 1));

  // Position the tooltip near the target, or center if no target.
  const vw = window.innerWidth, vh = window.innerHeight;
  const cardW = 340, cardH = 240;
  let cardStyle = { top: vh / 2 - cardH / 2, left: vw / 2 - cardW / 2 };

  if (rect) {
    const placement = s.placement || 'bottom';
    const margin = 16;
    const positions = {
      bottom: { top: rect.top + rect.height + margin, left: rect.left + rect.width / 2 - cardW / 2 },
      top:    { top: rect.top - cardH - margin,       left: rect.left + rect.width / 2 - cardW / 2 },
      right:  { top: rect.top + rect.height / 2 - cardH / 2, left: rect.left + rect.width + margin },
      left:   { top: rect.top + rect.height / 2 - cardH / 2, left: rect.left - cardW - margin },
    };
    cardStyle = positions[placement] || positions.bottom;
    cardStyle.top = Math.max(16, Math.min(vh - cardH - 16, cardStyle.top));
    cardStyle.left = Math.max(16, Math.min(vw - cardW - 16, cardStyle.left));
  }

  const bodyText = typeof s.body === 'function' ? s.body({ prospect, state }) : s.body;
  const showSpotlight = rect && s.placement !== 'center';
  const isActionStep = s.waitForClick || s.advanceOnScreen;

  return (
    <React.Fragment>
      {/* Dim the rest of the page - only when we have a real spotlight */}
      {showSpotlight && (
        <div style={{
          position: 'fixed', inset: 0, zIndex: 78,
          pointerEvents: 'none',
        }}>
          <div style={{
            position: 'absolute',
            top: rect.top - 6, left: rect.left - 6,
            width: rect.width + 12, height: rect.height + 12,
            borderRadius: 12,
            boxShadow: '0 0 0 9999px rgba(20,18,12,0.45), 0 0 0 2px var(--accent), 0 0 24px 2px rgba(216,149,87,0.4)',
            animation: isActionStep ? 'tour-pulse 1.6s ease-in-out infinite' : 'none',
            transition: 'top 280ms cubic-bezier(.2,.8,.2,1), left 280ms cubic-bezier(.2,.8,.2,1), width 280ms, height 280ms',
          }} />
        </div>
      )}

      {/* Dim overlay on non-spotlight (intro/outro) steps */}
      {!showSpotlight && (
        <div style={{
          position: 'fixed', inset: 0, zIndex: 78, pointerEvents: 'none',
          background: 'rgba(20,18,12,0.35)',
        }} />
      )}

      {/* Keyframes for the action-step pulse */}
      <style>{`@keyframes tour-pulse {
        0%, 100% { box-shadow: 0 0 0 9999px rgba(20,18,12,0.45), 0 0 0 2px var(--accent), 0 0 24px 2px rgba(216,149,87,0.4); }
        50%      { box-shadow: 0 0 0 9999px rgba(20,18,12,0.45), 0 0 0 3px var(--accent), 0 0 40px 6px rgba(216,149,87,0.7); }
      }`}</style>

      {/* Tooltip card */}
      <div style={{
        position: 'fixed', zIndex: 80,
        top: cardStyle.top, left: cardStyle.left, width: cardW,
        background: 'var(--surface)', border: '1px solid var(--border-strong)',
        borderRadius: 14, padding: '16px 18px 14px',
        boxShadow: '0 20px 60px -20px rgba(20,18,12,0.5), 0 2px 4px rgba(20,18,12,0.06)',
        fontFamily: 'var(--sans)',
        transition: 'top 280ms cubic-bezier(.2,.8,.2,1), left 280ms cubic-bezier(.2,.8,.2,1)',
        animation: 'slideUp 240ms ease',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
          <span style={{
            fontFamily: 'var(--mono)', fontSize: 10.5, color: 'var(--accent-ink)',
            background: 'var(--accent-tint)', border: '1px solid var(--accent-border)',
            padding: '2px 8px', borderRadius: 999, letterSpacing: 0.3,
          }}>{step + 1} of {TOUR_STEPS.length}</span>
          <button onClick={dismiss} title="Skip tour" style={{
            background: 'transparent', border: 'none', cursor: 'pointer',
            color: 'var(--ink-50)', padding: 4, borderRadius: 4, lineHeight: 0,
          }}><Icon name="x" size={14} /></button>
        </div>

        <div style={{
          fontFamily: 'var(--display)', fontSize: 22, lineHeight: 1.15,
          letterSpacing: -0.4, color: 'var(--ink)', marginBottom: 6,
        }}>{s.title}</div>

        <p style={{
          margin: '0 0 14px', fontSize: 13, lineHeight: 1.5,
          color: 'var(--ink-70)',
        }}>{bodyText}</p>

        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
          {step > 0 ? (
            <button onClick={back} style={{
              background: 'transparent', border: 'none', cursor: 'pointer',
              color: 'var(--ink-60)', fontSize: 12, padding: '4px 0',
              fontFamily: 'var(--sans)', display: 'inline-flex', alignItems: 'center', gap: 4,
            }}><Icon name="arrow-left" size={12} /> Back</button>
          ) : (
            <button onClick={dismiss} style={{
              background: 'transparent', border: 'none', cursor: 'pointer',
              color: 'var(--ink-60)', fontSize: 12, padding: '4px 0',
              fontFamily: 'var(--sans)',
            }}>Skip tour</button>
          )}

          {isActionStep ? (
            <span style={{
              fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--accent-ink)',
              letterSpacing: 0.3, display: 'inline-flex', alignItems: 'center', gap: 6,
            }}>
              <span style={{
                width: 6, height: 6, borderRadius: 3, background: 'var(--accent-deep)',
                animation: 'pulse 1.2s infinite',
              }} />
              WAITING FOR YOUR CLICK
            </span>
          ) : (
            <Btn variant="primary" size="sm" onClick={next}>
              {s.cta || (step === TOUR_STEPS.length - 1 ? 'Finish' : 'Next \u2192')}
            </Btn>
          )}
        </div>

        <div style={{ display: 'flex', gap: 3, marginTop: 12 }}>
          {TOUR_STEPS.map((_, i) => (
            <div key={i} style={{
              flex: 1, height: 2, borderRadius: 2,
              background: i <= step ? 'var(--accent)' : 'var(--border)',
              transition: 'background 200ms ease',
            }} />
          ))}
        </div>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, { Tour });
