/* ============================================================
   F2 UI — Feedback & overlays stories
   ============================================================ */
(function () {
  const F2 = window.F2;
  const { Icon, Button, IconButton, Alert, Banner, Toast, useToaster, ToastViewport, Tooltip, Popover, Modal, Drawer, Input, Badge } = F2;
  const G = 'Feedback';

  function Stage({ children, h = 360 }) {
    return <div style={{ position: 'relative', width: '100%', height: h, border: '1px solid var(--f2-border)', borderRadius: 'var(--f2-radius-md)', overflow: 'hidden', background: 'var(--f2-surface)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{children}</div>;
  }

  /* ---------------- Alert ---------------- */
  window.story({
    id: 'alert', group: G, name: 'Alert', status: 'new',
    tagline: 'Inline message tied to a region of the page. Five tones — info uses the amber accent; semantic tones stay distinct from it.',
    importLine: "const { Alert } = F2;",
    keywords: ['message', 'notice', 'inline', 'status'],
    props: [
      { name: 'tone', type: "'info' | 'neutral' | 'success' | 'warning' | 'error'", default: 'info', control: 'select', options: ['info', 'success', 'warning', 'error'], description: 'Semantic tone — sets icon, border and tint.' },
      { name: 'title', type: 'string', default: 'Agent deployed', control: 'text', description: 'Bold heading line.' },
      { name: 'children', type: 'ReactNode', description: 'Body copy.' },
      { name: 'icon', type: 'boolean', default: true, control: 'boolean', description: 'Show the leading tone icon.' },
      { name: 'onClose', type: '() => void', default: true, control: 'boolean', description: 'When set, renders a dismiss control.' },
      { name: 'action', type: 'ReactNode', default: false, control: 'boolean', description: 'Action row under the body.' },
    ],
    render: (v) => <Alert tone={v.tone} title={v.title} icon={v.icon} onClose={v.onClose ? () => {} : undefined}
      action={v.action ? <Button size="sm" variant="secondary">View run</Button> : undefined} style={{ width: 460, maxWidth: '100%' }}>
      The invoice-OCR agent is live and processing the queue.
    </Alert>,
    code: (v) => `<Alert\n  tone="${v.tone}"\n  title="${v.title}"${v.onClose ? '\n  onClose={() => setShown(false)}' : ''}${v.action ? '\n  action={<Button size="sm" variant="secondary">View run</Button>}' : ''}\n>\n  The invoice-OCR agent is live and processing the queue.\n</Alert>`,
    examples: [
      { name: 'info', render: () => <Alert tone="info" title="Heads up" style={{ width: 280 }}>New model available.</Alert> },
      { name: 'success', render: () => <Alert tone="success" title="Deployed" style={{ width: 280 }}>Agent is live.</Alert> },
      { name: 'warning', render: () => <Alert tone="warning" title="Degraded" style={{ width: 280 }}>Throughput is below target.</Alert> },
      { name: 'error', render: () => <Alert tone="error" title="Run failed" style={{ width: 280 }}>Tool call timed out.</Alert> },
    ],
    a11y: [
      'Error/warning alerts render <code>role="alert"</code> (assertive); info/success use <code>role="status"</code> (polite) so they do not interrupt.',
      'Tone is conveyed by icon + text, not color alone. Warning stays distinct from the brand amber.',
      'The dismiss control has an accessible "Dismiss" label.',
    ],
  });

  /* ---------------- Banner ---------------- */
  function BannerDemo(v) {
    const [show, setShow] = React.useState(true);
    return (
      <div style={{ width: '100%', position: 'absolute', top: 0, left: 0 }}>
        {show ? <Banner tone={v.tone} onClose={v.dismissible ? () => setShow(false) : undefined}
          action={<Button size="sm" variant={v.tone === 'info' ? 'primary' : 'secondary'}>Upgrade</Button>}>
          You've used 82% of your monthly agent runs.
        </Banner> : <div style={{ padding: 16, textAlign: 'center', color: 'var(--f2-text-faint)', fontFamily: 'var(--f2-font-mono)', fontSize: 12 }}>dismissed — <button onClick={() => setShow(true)} style={{ background: 'none', border: 'none', color: 'var(--f2-accent-text)', cursor: 'pointer', font: 'inherit' }}>restore</button></div>}
      </div>
    );
  }
  window.story({
    id: 'banner', group: G, name: 'Banner', status: 'new',
    tagline: 'A full-width page-level notice — sits at the top of an app shell with an inline action and optional dismiss.',
    importLine: "const { Banner } = F2;",
    keywords: ['banner', 'announce', 'notice', 'top'],
    props: [
      { name: 'tone', type: "'info' | 'success' | 'warning' | 'error'", default: 'warning', control: 'select', options: ['info', 'success', 'warning', 'error'], description: 'Semantic tone.' },
      { name: 'children', type: 'ReactNode', description: 'Banner message.' },
      { name: 'action', type: 'ReactNode', description: 'Trailing action.' },
      { name: 'dismissible', type: 'boolean', default: true, control: 'boolean', description: 'Show a dismiss control.' },
    ],
    render: (v) => <Stage h={140}><BannerDemo {...v} /></Stage>,
    code: (v) => `<Banner\n  tone="${v.tone}"${v.dismissible ? '\n  onClose={() => dismiss()}' : ''}\n  action={<Button size="sm">Upgrade</Button>}\n>\n  You've used 82% of your monthly agent runs.\n</Banner>`,
    a11y: [
      'Place the banner as the first child of the app shell so it is encountered early in the reading order.',
      'Keep the message short; move detail behind the action link.',
    ],
  });

  /* ---------------- Toast ---------------- */
  function ToastDemo(v) {
    const { toasts, push, dismiss } = useToaster(4000);
    return (
      <Stage h={360}>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'center' }}>
          <Button variant="secondary" size="sm" onClick={() => push({ tone: 'success', title: 'Deployed', message: 'invoice-ocr is live.' })}>Success</Button>
          <Button variant="secondary" size="sm" onClick={() => push({ tone: 'error', title: 'Run failed', message: 'Tool call timed out.' })}>Error</Button>
          <Button variant="secondary" size="sm" onClick={() => push({ tone: 'info', title: 'Syncing', message: 'Pulling latest records…' })}>Info</Button>
        </div>
        <ToastViewport contained placement={v.placement} toasts={toasts} onDismiss={dismiss} />
      </Stage>
    );
  }
  window.story({
    id: 'toast', group: G, name: 'Toast', status: 'new',
    tagline: 'Transient confirmations in a stacked viewport. Ships with a useToaster() hook and a positioned ToastViewport.',
    importLine: "const { useToaster, ToastViewport } = F2;",
    keywords: ['toast', 'notification', 'snackbar', 'transient'],
    props: [
      { name: 'placement', type: "'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'", default: 'bottom-right', control: 'select', options: ['bottom-right', 'bottom-left', 'top-right', 'top-left'], description: 'Where the stack appears.' },
      { name: 'tone', type: "'neutral' | 'success' | 'warning' | 'error' | 'info'", description: 'Per-toast tone (passed to push()).' },
      { name: 'timeout', type: 'number', default: 4000, description: 'Auto-dismiss ms; pass 0 to keep until closed.' },
    ],
    render: (v) => <ToastDemo {...v} />,
    code: () => `const { toasts, push, dismiss } = useToaster();\n\n<Button onClick={() => push({\n  tone: 'success',\n  title: 'Deployed',\n  message: 'invoice-ocr is live.',\n})}>Deploy</Button>\n\n<ToastViewport\n  placement="bottom-right"\n  toasts={toasts}\n  onDismiss={dismiss}\n/>`,
    a11y: [
      'The viewport is an <code>aria-live="polite"</code> region, so new toasts are announced without stealing focus.',
      'Each toast carries a dismiss button; provide a long-enough timeout (or 0) for users who need to read it.',
      'Tone is reinforced by icon and an accent left-border, not color alone.',
    ],
    notes: '<code>useToaster(defaultTimeout)</code> returns <code>{ toasts, push, dismiss }</code>. In a real app, lift it to a provider so any component can call <code>push()</code>.',
  });

  /* ---------------- Tooltip ---------------- */
  window.story({
    id: 'tooltip', group: G, name: 'Tooltip', status: 'new',
    tagline: 'A small label on hover or focus. Four placements; appears on a sunken surface with a hairline.',
    importLine: "const { Tooltip } = F2;",
    keywords: ['tooltip', 'hint', 'hover', 'label'],
    props: [
      { name: 'content', type: 'ReactNode', default: 'Re-run this step', control: 'text', description: 'Tooltip text.' },
      { name: 'placement', type: "'top' | 'bottom' | 'left' | 'right'", default: 'top', control: 'select', options: ['top', 'bottom', 'left', 'right'], description: 'Side relative to the trigger.' },
      { name: 'children', type: 'ReactNode', description: 'The trigger element.' },
    ],
    render: (v) => <Tooltip content={v.content} placement={v.placement}><IconButton variant="solid" aria-label="Re-run"><Icon name="RefreshCw" size={18} /></IconButton></Tooltip>,
    code: (v) => `<Tooltip content="${v.content}" placement="${v.placement}">\n  <IconButton aria-label="Re-run"><Icon name="RefreshCw" /></IconButton>\n</Tooltip>`,
    examples: [
      { name: 'top', render: () => <Tooltip content="Top" placement="top"><Button size="sm" variant="secondary">Hover</Button></Tooltip> },
      { name: 'bottom', render: () => <Tooltip content="Bottom" placement="bottom"><Button size="sm" variant="secondary">Hover</Button></Tooltip> },
      { name: 'right', render: () => <Tooltip content="Right" placement="right"><Button size="sm" variant="secondary">Hover</Button></Tooltip> },
    ],
    a11y: [
      'Shows on <strong>focus</strong> as well as hover, so keyboard users get the hint.',
      'The bubble is <code>role="tooltip"</code>; keep content short and non-essential — never hide the only copy of critical info in a tooltip.',
    ],
  });

  /* ---------------- Popover ---------------- */
  window.story({
    id: 'popover', group: G, name: 'Popover', status: 'new',
    tagline: 'A click-anchored floating panel for rich content — menus, filters, quick forms. Closes on outside click or Esc.',
    importLine: "const { Popover } = F2;",
    keywords: ['popover', 'dropdown', 'panel', 'anchored'],
    props: [
      { name: 'trigger', type: 'ReactNode', description: 'Element that toggles the panel.' },
      { name: 'children', type: 'ReactNode | (close) => ReactNode', description: 'Panel content; receives a close() callback when a function.' },
      { name: 'align', type: "'start' | 'center' | 'end'", default: 'start', control: 'select', options: ['start', 'center', 'end'], description: 'Horizontal alignment to the trigger.' },
      { name: 'placement', type: "'bottom' | 'top'", default: 'bottom', control: 'select', options: ['bottom', 'top'], description: 'Vertical side.' },
      { name: 'width', type: 'number', default: 260, description: 'Panel width in px.' },
    ],
    render: (v) => (
      <Popover align={v.align} placement={v.placement} trigger={<Button variant="secondary" iconRight={<Icon name="ChevronDown" size={15} />}>Filter</Button>}>
        {(close) => (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            <div style={{ fontFamily: 'var(--f2-font-mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--f2-text-faint)' }}>Status</div>
            {['Running', 'Paused', 'Failed'].map((s) => <label key={s} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14, color: 'var(--f2-text)', cursor: 'pointer' }}><input type="checkbox" defaultChecked={s === 'Running'} style={{ accentColor: 'var(--f2-accent)' }} /> {s}</label>)}
            <Button size="sm" onClick={close} style={{ marginTop: 4 }}>Apply</Button>
          </div>
        )}
      </Popover>
    ),
    code: (v) => `<Popover\n  align="${v.align}"\n  trigger={<Button variant="secondary">Filter</Button>}\n>\n  {(close) => (\n    <FilterForm onApply={close} />\n  )}\n</Popover>`,
    a11y: [
      'Panel is <code>role="dialog"</code>; it closes on outside click and <kbd>Esc</kbd>.',
      'For a list of actions prefer <strong>DropdownMenu</strong> (roving focus + arrow keys); use Popover for rich content.',
    ],
  });

  /* ---------------- Modal ---------------- */
  function ModalDemo(v) {
    const [open, setOpen] = React.useState(false);
    return (
      <Stage>
        <Button onClick={() => setOpen(true)}>Open modal</Button>
        <Modal contained open={open} onClose={() => setOpen(false)} size={v.size}
          title="Deploy invoice agent?" description="This will route live invoices through the agent."
          footer={<><Button variant="secondary" onClick={() => setOpen(false)}>Cancel</Button><Button iconRight={<Icon name="ArrowRight" size={16} />} onClick={() => setOpen(false)}>Deploy</Button></>}>
          <div style={{ fontSize: 14.5, lineHeight: 1.6, color: 'var(--f2-text-secondary)' }}>
            The agent will process the existing queue of 1,284 invoices. You can pause it at any time from the run view.
          </div>
        </Modal>
      </Stage>
    );
  }
  window.story({
    id: 'modal', group: G, name: 'Modal', status: 'new',
    tagline: 'A centered dialog over a dimmed backdrop. Header, scrollable body, footer actions; closes on backdrop click or Esc.',
    importLine: "const { Modal } = F2;",
    keywords: ['dialog', 'modal', 'confirm', 'overlay'],
    props: [
      { name: 'open', type: 'boolean', description: 'Controls visibility.' },
      { name: 'onClose', type: '() => void', description: 'Called on backdrop click, Esc, or close button.' },
      { name: 'title', type: 'string', description: 'Dialog heading + accessible name.' },
      { name: 'description', type: 'string', description: 'Sub-heading under the title.' },
      { name: 'footer', type: 'ReactNode', description: 'Action row (right-aligned).' },
      { name: 'size', type: "'sm' | 'md' | 'lg'", default: 'md', control: 'select', options: ['sm', 'md', 'lg'], description: 'Dialog width — 380 / 480 / 640px.' },
      { name: 'contained', type: 'boolean', default: false, description: 'Render absolutely within a positioned parent (used here to stay inside the canvas).' },
    ],
    render: (v) => <ModalDemo {...v} />,
    code: (v) => `const [open, setOpen] = useState(false);\n<Button onClick={() => setOpen(true)}>Open modal</Button>\n<Modal\n  open={open}\n  onClose={() => setOpen(false)}\n  size="${v.size}"\n  title="Deploy invoice agent?"\n  description="This will route live invoices through the agent."\n  footer={<>\n    <Button variant="secondary" onClick={() => setOpen(false)}>Cancel</Button>\n    <Button onClick={deploy}>Deploy</Button>\n  </>}\n>\n  …\n</Modal>`,
    a11y: [
      'The dialog uses <code>role="dialog"</code> + <code>aria-modal="true"</code> and is named by its title.',
      'Closes on <kbd>Esc</kbd> and backdrop click; the close button is labelled.',
      'In production, trap focus within the dialog and restore it to the trigger on close.',
    ],
  });

  /* ---------------- Drawer ---------------- */
  function DrawerDemo(v) {
    const [open, setOpen] = React.useState(false);
    return (
      <Stage>
        <Button onClick={() => setOpen(true)} iconLeft={<Icon name="PanelRight" size={16} />}>Open drawer</Button>
        <Drawer contained open={open} onClose={() => setOpen(false)} side={v.side} width={v.width} title="Run details"
          footer={<Button variant="secondary" onClick={() => setOpen(false)}>Close</Button>}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}><Badge tone="success">Completed</Badge><span style={{ fontFamily: 'var(--f2-font-mono)', fontSize: 12, color: 'var(--f2-text-faint)' }}>run_8c21</span></div>
            <Input label="Trigger" defaultValue="webhook · stripe.invoice" />
            <div style={{ fontSize: 14, color: 'var(--f2-text-secondary)', lineHeight: 1.6 }}>Processed 142 records in 19s. No exceptions raised.</div>
          </div>
        </Drawer>
      </Stage>
    );
  }
  window.story({
    id: 'drawer', group: G, name: 'Drawer', status: 'new',
    tagline: 'A side panel that slides in for detail or secondary tasks without leaving the page.',
    importLine: "const { Drawer } = F2;",
    keywords: ['drawer', 'panel', 'sheet', 'side'],
    props: [
      { name: 'open', type: 'boolean', description: 'Controls visibility.' },
      { name: 'onClose', type: '() => void', description: 'Called on backdrop click / Esc / close.' },
      { name: 'title', type: 'string', description: 'Header + accessible name.' },
      { name: 'side', type: "'right' | 'left'", default: 'right', control: 'select', options: ['right', 'left'], description: 'Edge to dock to.' },
      { name: 'width', type: 'number', default: 380, control: 'number', min: 280, max: 460, step: 20, description: 'Drawer width in px.' },
      { name: 'footer', type: 'ReactNode', description: 'Footer action row.' },
    ],
    render: (v) => <DrawerDemo {...v} />,
    code: (v) => `const [open, setOpen] = useState(false);\n<Drawer\n  open={open}\n  onClose={() => setOpen(false)}\n  side="${v.side}"\n  width={${v.width}}\n  title="Run details"\n>\n  …\n</Drawer>`,
    a11y: [
      'Same dialog semantics as Modal — <code>role="dialog"</code>, <code>aria-modal</code>, named by title, Esc to close.',
      'Slide animation respects <code>prefers-reduced-motion</code> via the F2 motion tokens.',
    ],
  });
})();
