// dashboard-scenes.jsx: the four scenes of the Overview demo (23.5 s loop).
//   0.0 to  5.0  SceneOverview  the Overview: company header, Legal Coverage, the assistant
//   5.0 to 11.5  SceneAsk       a question in plain English, answered with template cards
//  11.5 to 16.5  SceneContext   five sources pool into what we know about the company
//  16.5 to 22.5  SceneDispute   the free dispute viability check
// (The review scene moved to the Document Review demo, and the closing tagline
// went: the card beside this demo already says "Your company at a glance".)
/* global OV, Icon, useLiveAnchor, Appear, OverviewPage, ConversationPanel, DockedComposer,
   UserBubble, AgentText, TypingDots, StepLine, FileChip, TemplateCard, IntakeChips, Assessment, OutlineButton, IndigoButton, SceneCaption,
   useSprite, Easing, interpolate, clamp */

// Entry and exit fades shared by every scene.
function fadeInOut(t, duration, { fadeIn = true, fadeOut = true } = {}) {
  const enter = fadeIn ? Easing.easeOutCubic(clamp(t / 0.4, 0, 1)) : 1;
  const exit = fadeOut ? 1 - clamp((t - (duration - 0.4)) / 0.4, 0, 1) : 1;
  return enter * exit;
}

// The app's arrow cursor, drawn at the stage's 2x scale.
function BigCursor({ x, y, clicking = false, opacity = 1 }) {
  return (
    <div style={{
      position: 'absolute', left: x, top: y, transform: 'translate(-4px, -4px)',
      pointerEvents: 'none', zIndex: 1000, opacity,
    }}>
      {clicking && (
        <div style={{
          position: 'absolute', left: -24, top: -24, width: 60, height: 60, borderRadius: 30,
          background: 'rgba(28,25,23,0.14)',
        }}/>
      )}
      <svg width="44" height="52" viewBox="0 0 22 26" style={{ filter: 'drop-shadow(0 3px 5px rgba(0,0,0,0.25))' }}>
        <path d="M2 2 L2 20 L7 16 L10 23 L13 22 L10 15 L17 15 Z" fill="#1C1917" stroke="#FFFFFF" strokeWidth="1.25" strokeLinejoin="round"/>
      </svg>
    </div>
  );
}

// A cursor path through anchor points: [time, point] pairs, eased per leg.
function cursorAt(t, keys) {
  const times = keys.map((k) => k[0]);
  const ease = Easing.easeInOutCubic;
  return {
    x: interpolate(times, keys.map((k) => k[1].x), ease)(t),
    y: interpolate(times, keys.map((k) => k[1].y), ease)(t),
  };
}

const typedText = (full, t, start, end) => full.slice(0, Math.floor(clamp((t - start) / (end - start), 0, 1) * full.length));

// ─── Scene 1: the Overview ────────────────────────────────────────────────
function SceneOverview() {
  const { localTime: t } = useSprite();
  const pct = interpolate([0.5, 2.0], [0, 38], Easing.easeOutCubic)(t);
  const settle = Easing.easeOutCubic(clamp(t / 0.8, 0, 1));
  return (
    <div style={{
      position: 'absolute', inset: 0,
      opacity: Easing.easeOutCubic(clamp(t / 0.4, 0, 1)),
      transform: `scale(${1.03 - 0.03 * settle})`, transformOrigin: 'center',
    }}>
      <OverviewPage pct={pct} entry={t} />
      <SceneCaption show={t > 0.4 && t < 4.7}>YOUR COMPANY AT A GLANCE</SceneCaption>
    </div>
  );
}

// ─── Scene 2: ask a question, get template cards ──────────────────────────
const QUESTION = 'I want to hire my first employee. What do I need?';

function SceneAsk() {
  const { localTime: t, duration } = useSprite();
  const rootRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const sendRef = React.useRef(null);
  const prepareRef = React.useRef(null);
  const input = useLiveAnchor(inputRef, rootRef) || { x: 760, y: 560 };
  const sendBtn = useLiveAnchor(sendRef, rootRef) || { x: 1620, y: 560 };
  const prepare = useLiveAnchor(prepareRef, rootRef) || { x: 560, y: 900 };

  const inThread = t >= 2.95;
  const threadIn = Easing.easeOutCubic(clamp((t - 2.95) / 0.3, 0, 1));
  const typed = typedText(QUESTION, t, 0.9, 2.5);

  const offRight = { x: input.x + 820, y: input.y + 420 };
  const pos = inThread
    ? cursorAt(t, [[4.7, { x: prepare.x + 520, y: prepare.y + 260 }], [5.5, prepare]])
    : cursorAt(t, [[0, offRight], [0.7, { x: input.x - 360, y: input.y }], [2.5, { x: input.x - 340, y: input.y + 10 }], [2.8, sendBtn]]);
  const clicking = (t > 0.68 && t < 0.86) || (t > 2.8 && t < 2.96);
  const cursorOpacity = inThread ? clamp((t - 4.7) / 0.3, 0, 1) : clamp(t / 0.3, 0, 1) * (1 - clamp((t - 2.9) / 0.15, 0, 1));

  return (
    <div ref={rootRef} style={{ position: 'absolute', inset: 0, opacity: fadeInOut(t, duration, { fadeIn: false }) }}>
      {!inThread || threadIn < 1 ? (
        <OverviewPage pct={38} entry={10} composerValue={typed} composerFocused={t > 0.75} inputRef={inputRef} sendRef={sendRef} />
      ) : null}
      {inThread && (
        <div style={{ position: 'absolute', inset: 0, opacity: threadIn }}>
          <ConversationPanel
            title="First employee hire"
            composer={<DockedComposer />}
          >
            <Appear at={3.05} t={t}><UserBubble>{QUESTION}</UserBubble></Appear>
            {t > 3.3 && t < 3.85 && <TypingDots />}
            <Appear at={3.85} t={t}>
              <AgentText>
                Most first hires start with one of these two agreements.
              </AgentText>
            </Appear>
            <Appear at={4.1} t={t}>
              <AgentText style={{ fontSize: 28 }}>
                If you are looking to hire someone, these templates are free to use. We can prepare one with you here.
              </AgentText>
            </Appear>
            {t >= 4.3 && (
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
                <Appear at={4.3} t={t}>
                  <TemplateCard
                    primary
                    buttonRef={prepareRef}
                    name="Employment Agreement (Full-Time)"
                    description="A full-time employment agreement for an Australian employer engaging a permanent employee, covering pay, leave, confidentiality, intellectual property and termination."
                  />
                </Appear>
                <Appear at={4.45} t={t}>
                  <TemplateCard
                    name="Independent Contractor Agreement"
                    description="For engaging an individual or a business as an independent contractor rather than an employee, covering the services, fees, intellectual property and confidentiality."
                  />
                </Appear>
              </div>
            )}
          </ConversationPanel>
        </div>
      )}
      <BigCursor x={pos.x} y={pos.y} clicking={clicking} opacity={cursorOpacity * fadeInOut(t, duration, { fadeIn: false })} />
      <SceneCaption show={t > 0.3 && t < duration - 0.3} placement={inThread ? 'top' : 'bottom'}>ASK IN PLAIN ENGLISH</SceneCaption>
    </div>
  );
}

// ─── Scene 3: what we know about the company ──────────────────────────────
// Five sources pool into one company knowledge card (the company brief and
// company memory behind the Overview assistant).
const WEB_CENTRE = { x: 960, y: 530 };
const SOURCES = [
  { id: 'docs',     at: 0.5, angle: -90,  icon: 'fileText',      title: 'Your documents',
    fact: 'Shareholders agreement, 3 employment agreements, lease' },
  { id: 'site',     at: 1.1, angle: -18,  icon: 'globe',         title: 'Your website',
    fact: 'Sells software subscriptions to customers in Australia' },
  { id: 'chat',     at: 1.7, angle: 54,   icon: 'messageSquare', title: 'What you tell us',
    fact: 'Raising a seed round in the first quarter' },
  { id: 'registry', at: 2.3, angle: 126,  icon: 'building2',     title: 'Company registry',
    fact: 'Pty Ltd, 2 directors, registered in Queensland' },
  { id: 'dates',    at: 2.9, angle: 198,  icon: 'calendarClock', title: 'Your deadlines',
    fact: 'Annual review due 14 November' },
];
const RING = { rx: 620, ry: 400 };

function sourcePos(angle) {
  const a = (angle * Math.PI) / 180;
  return { x: WEB_CENTRE.x + Math.cos(a) * RING.rx, y: WEB_CENTRE.y + Math.sin(a) * RING.ry };
}

function SourceNode({ source, t }) {
  const k = Easing.easeOutCubic(clamp((t - source.at) / 0.4, 0, 1));
  const p = sourcePos(source.angle);
  return (
    <div style={{
      position: 'absolute', left: p.x, top: p.y - 48, height: 96, whiteSpace: 'nowrap',
      display: 'inline-flex', alignItems: 'center', gap: 18, padding: '0 30px 0 22px', boxSizing: 'border-box',
      borderRadius: 28, background: OV.surface, border: `2px solid ${OV.line}`,
      boxShadow: '0 4px 24px rgba(28,25,23,0.06)',
      opacity: k, transform: `translateX(-50%) scale(${0.85 + 0.15 * k})`,
    }}>
      <div style={{
        width: 52, height: 52, borderRadius: 16, background: OV.indigoWeak, color: OV.indigo,
        display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      }}>
        <Icon name={source.icon} size={28} />
      </div>
      <div style={{ fontSize: 25, fontWeight: 600, color: OV.ink, whiteSpace: 'nowrap' }}>{source.title}</div>
    </div>
  );
}

// The threads from each source into the centre, drawn in, with a spark that
// travels along each one as it connects.
function WebThreads({ t }) {
  return (
    <svg width="1920" height="1080" viewBox="0 0 1920 1080" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
      {SOURCES.map((s) => {
        const p = sourcePos(s.angle);
        const draw = Easing.easeOutCubic(clamp((t - s.at - 0.15) / 0.45, 0, 1));
        const travel = Easing.easeInOutCubic(clamp((t - s.at - 0.35) / 0.5, 0, 1));
        const len = Math.hypot(WEB_CENTRE.x - p.x, WEB_CENTRE.y - p.y);
        const sx = p.x + (WEB_CENTRE.x - p.x) * travel;
        const sy = p.y + (WEB_CENTRE.y - p.y) * travel;
        const sparkOn = travel > 0 && travel < 1;
        return (
          <g key={s.id}>
            <line
              x1={p.x} y1={p.y} x2={WEB_CENTRE.x} y2={WEB_CENTRE.y}
              stroke={OV.indigo} strokeWidth="3" strokeLinecap="round" strokeOpacity="0.35"
              strokeDasharray={len} strokeDashoffset={len * (1 - draw)}
            />
            {sparkOn && (
              <>
                <circle cx={sx} cy={sy} r="18" fill={OV.indigo} fillOpacity="0.18" />
                <circle cx={sx} cy={sy} r="8" fill={OV.indigo} />
              </>
            )}
          </g>
        );
      })}
    </svg>
  );
}

function KnowledgeCard({ t }) {
  const k = Easing.easeOutCubic(clamp(t / 0.5, 0, 1));
  const known = SOURCES.filter((s) => t >= s.at + 0.75);
  const pulse = SOURCES.some((s) => t >= s.at + 0.72 && t < s.at + 0.95);
  return (
    <div style={{
      position: 'absolute', left: WEB_CENTRE.x - 230, top: WEB_CENTRE.y - 165, width: 460,
      borderRadius: 32, background: OV.surface, border: `2px solid ${pulse ? OV.indigo : OV.line}`,
      boxShadow: pulse ? `0 0 0 8px ${OV.indigoWeak}, 0 12px 48px rgba(28,25,23,0.10)` : '0 12px 48px rgba(28,25,23,0.10)',
      padding: '26px 30px 22px', boxSizing: 'border-box',
      opacity: k, transform: `scale(${0.9 + 0.1 * k})`,
      transition: 'border-color 220ms, box-shadow 220ms',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 6 }}>
        <div style={{
          width: 48, height: 48, borderRadius: 14, background: OV.ink, color: '#FFFFFF',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name="bookOpen" size={26} />
        </div>
        <div>
          <div style={{ fontSize: 26, fontWeight: 700, color: OV.ink, letterSpacing: '-0.01em' }}>What we know</div>
          <div style={{ fontSize: 19, color: OV.muted }}>Frontier Capital Pty Ltd</div>
        </div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 14, minHeight: 190 }}>
        {known.length === 0 && (
          <div style={{ fontSize: 20, color: OV.muted, fontStyle: 'italic' }}>Building up as you use the platform…</div>
        )}
        {known.map((s) => {
          const kk = Easing.easeOutCubic(clamp((t - s.at - 0.75) / 0.35, 0, 1));
          return (
            <div key={s.id} style={{
              display: 'flex', alignItems: 'flex-start', gap: 10, fontSize: 20, lineHeight: 1.35, color: OV.ink,
              opacity: kk, transform: `translateX(${(1 - kk) * -12}px)`,
            }}>
              <Icon name="check" size={20} color={OV.success} />
              <span>{s.fact}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function SceneContext() {
  const { localTime: t, duration } = useSprite();

  return (
    <div style={{ position: 'absolute', inset: 0, opacity: fadeInOut(t, duration), fontFamily: OV.body }}>
      <WebThreads t={t} />
      {SOURCES.map((s) => <SourceNode key={s.id} source={s} t={t} />)}
      <KnowledgeCard t={t} />

      <SceneCaption show={t > 0.3 && t < duration - 0.3} placement="bottom">WHAT WE KNOW ABOUT YOUR COMPANY</SceneCaption>
    </div>
  );
}

// ─── Scene 4: the dispute viability check ─────────────────────────────────
const DISPUTE_TYPES = ['Contract / Agreement', 'Employment', 'Business / Shareholder', 'Property', 'Crypto / Digital assets', 'Payment / Debt'];
const STAKES = ['Under $10,000', '$10,000 - $50,000', '$50,000 - $250,000', '$250,000+', 'Not sure'];

function SceneDispute() {
  const { localTime: t, duration } = useSprite();
  const rootRef = React.useRef(null);
  const typeRef = React.useRef(null);
  const stakeRef = React.useRef(null);
  const reviewRef = React.useRef(null);
  const typeChip = useLiveAnchor(typeRef, rootRef) || { x: 900, y: 700 };
  const stakeChip = useLiveAnchor(stakeRef, rootRef) || { x: 700, y: 760 };
  const reviewBtn = useLiveAnchor(reviewRef, rootRef) || { x: 520, y: 860 };

  const pos = t < 1.2
    ? cursorAt(t, [[0.3, { x: typeChip.x + 300, y: typeChip.y + 280 }], [0.95, typeChip]])
    : t < 2.3
      ? cursorAt(t, [[1.2, typeChip], [2.0, stakeChip]])
      : cursorAt(t, [[3.7, { x: reviewBtn.x + 560, y: reviewBtn.y + 200 }], [4.5, reviewBtn]]);
  const clicking = (t > 0.98 && t < 1.14) || (t > 2.03 && t < 2.19);
  const cursorOpacity = t < 2.3
    ? clamp((t - 0.3) / 0.3, 0, 1) * (1 - clamp((t - 2.2) / 0.1, 0, 1))
    : clamp((t - 3.7) / 0.3, 0, 1) * (1 - clamp((t - (duration - 0.5)) / 0.3, 0, 1));

  const typeAnswered = t >= 1.15;
  const stakeAnswered = t >= 2.2;
  const assessed = t >= 2.9;

  return (
    <div ref={rootRef} style={{ position: 'absolute', inset: 0, opacity: fadeInOut(t, duration) }}>
      <ConversationPanel
        title={typeAnswered ? 'Payment dispute' : 'New conversation'}
        subtitle="Dispute check"
        composer={
          <DockedComposer
            placeholder={assessed ? 'Ask a follow-up question…' : typeAnswered ? 'Choose an option above, or type your answer' : 'Or type your own answer…'}
          />
        }
      >
        <Appear at={0.1} t={t}>
          <AgentText>A few quick questions first. What type of dispute is this?</AgentText>
        </Appear>
        {!typeAnswered && (
          <Appear at={0.25} t={t}>
            <IntakeChips options={DISPUTE_TYPES} chosen={t > 1.0 ? 'Payment / Debt' : null} chipRefs={{ 'Payment / Debt': typeRef }} />
          </Appear>
        )}
        <Appear at={1.15} t={t}><UserBubble>Payment / Debt</UserBubble></Appear>
        <Appear at={1.3} t={t}><AgentText>Approximately how much is at stake?</AgentText></Appear>
        {!stakeAnswered && (
          <Appear at={1.45} t={t}>
            <IntakeChips options={STAKES} chosen={t > 2.05 ? '$10,000 - $50,000' : null} chipRefs={{ '$10,000 - $50,000': stakeRef }} />
          </Appear>
        )}
        <Appear at={2.2} t={t}><UserBubble>$10,000 - $50,000</UserBubble></Appear>
        {t > 2.35 && t < 2.9 && <TypingDots />}
        <Appear at={2.9} t={t}><Assessment /></Appear>
        <Appear at={3.4} t={t}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <IndigoButton icon="scale" buttonRef={reviewRef}>Get Reviewed by Gosai Law</IndigoButton>
            <OutlineButton icon="phone">Book a Call</OutlineButton>
            <div style={{ padding: '18px 20px', fontSize: 24, color: OV.muted }}>Back to the assistant</div>
          </div>
        </Appear>
      </ConversationPanel>
      <BigCursor x={pos.x} y={pos.y} clicking={clicking} opacity={cursorOpacity} />
      <SceneCaption show={t > 0.3 && t < duration - 0.3} placement="top">A FREE VIABILITY CHECK</SceneCaption>
    </div>
  );
}

Object.assign(window, {
  SceneOverview, SceneAsk, SceneContext, SceneDispute, BigCursor,
});
