import type { Meta, StoryFn } from '@storybook/react'
import React from 'react'

import type { RichCardActionButton, RichCardBaseProps } from './types'

import RichCard from '.'

const IMAGE = '/image-thumbnail.jpg'
const IMAGE_2 = '/video-thumbnail.jpg'
const IMAGE_3 = '/document-thumbnail.jpg'

const meta: Meta = {
  title: 'RichCard',
  parameters: {
    layout: 'fullscreen',
    // Matrix canvases are design-review surfaces, not regression targets — a
    // single-pixel change in one cell would diff the whole grid. Default off;
    // the stories that ARE regression targets opt back in per-story below.
    chromatic: { disableSnapshot: true },
  },
}
export default meta

/* ── Story scaffold (mirrors LinkAttachment.stories) ─────────────────── */

const Table = ({ children }: { children: React.ReactNode }) => (
  <div className="min-h-screen w-full bg-[#F9F7F4] p-12">
    <table className="border-separate border-spacing-4">{children}</table>
  </div>
)

const TableHead = ({ columns }: { columns: string[] }) => (
  <thead>
    <tr>
      <th className="pb-2 text-left text-xs font-medium text-black/40" />
      {columns.map((column) => (
        <th
          key={column}
          className="pb-2 text-left text-xs font-medium text-black/40"
        >
          {column}
        </th>
      ))}
    </tr>
  </thead>
)

const RowLabel = ({ children }: { children: React.ReactNode }) => (
  <td className="pr-4 pt-2 text-right align-top text-xs font-medium text-black/40">
    {children}
  </td>
)

const Cell = ({ children }: { children: React.ReactNode }) => (
  <td className="align-top">{children}</td>
)

/* ── Shared fixtures ─────────────────────────────────────────────────── */

const primary = (label: string): RichCardActionButton => ({
  label,
  variant: 'primary',
  onClick: () => alert(`Tapped ${label}`),
})
const secondaryLink = (label: string, url: string): RichCardActionButton => ({
  label,
  variant: 'secondary',
  href: url,
})
const secondary = (label: string): RichCardActionButton => ({
  label,
  variant: 'secondary',
  onClick: () => alert(`Tapped ${label}`),
})

// The three canonical surfaces the card converges (interactive-surfaces.md).
const OFFICIAL_WELCOME: RichCardBaseProps = {
  title: 'Set up your welcome message',
  subtitle: 'Automatically greet new followers the moment they message you.',
  images: [IMAGE],
  imagePresentation: 'hero',
  actions: [primary('Set up welcome message')],
}
const SINGLE_LINK: RichCardBaseProps = {
  title: 'Check out my new drop',
  subtitle: 'Fresh merch, live now — grab it before it’s gone.',
  images: [IMAGE],
  imagePresentation: 'hero',
  actions: [secondaryLink('Shop now', 'tr.ee/briedrop')],
}
const COLLECTION: RichCardBaseProps = {
  title: 'My summer collection',
  subtitle: 'Three new looks, styled and ready.',
  images: [IMAGE, IMAGE_2, IMAGE_3],
  imagePresentation: 'fan',
  actions: [secondaryLink('View collection', 'tr.ee/briesummer')],
}
const NEWLINE_SUBTITLE: RichCardBaseProps = {
  ...OFFICIAL_WELCOME,
  title: 'Start every conversation with a personal welcome message!',
  subtitle:
    '👋 Say hello as people arrive\n✨ Spark conversations\n💬 Add automated FAQs',
  subtitleLines: 6,
}

const bothSides = (props: RichCardBaseProps) => (
  <>
    <Cell>
      <RichCard.Received {...props} />
    </Cell>
    <Cell>
      <RichCard.Sent {...props} />
    </Cell>
  </>
)

/* ── Instances — the headline: one card, three surfaces ──────────────── */

/**
 * The three real surfaces that converge on `linktree_rich_card`, each shown
 * Received (light) and Sent (dark). They differ only by knobs: the official
 * welcome card is `hero + primary`; a single-link broadcast is `hero +
 * secondary`; a collection is `fan + secondary`. A fourth row shows a
 * newline-separated subtitle (the onboarding result-card shape).
 */
export const Instances: StoryFn = () => (
  <Table>
    <TableHead columns={['Received (light)', 'Sent (dark)']} />
    <tbody>
      <tr>
        <RowLabel>Official welcome — hero · primary</RowLabel>
        {bothSides(OFFICIAL_WELCOME)}
      </tr>
      <tr>
        <RowLabel>Single link — hero · secondary</RowLabel>
        {bothSides(SINGLE_LINK)}
      </tr>
      <tr>
        <RowLabel>Collection — fan · secondary</RowLabel>
        {bothSides(COLLECTION)}
      </tr>
      <tr>
        <RowLabel>Subtitle with newlines</RowLabel>
        {bothSides(NEWLINE_SUBTITLE)}
      </tr>
    </tbody>
  </Table>
)
Instances.parameters = { chromatic: { disableSnapshot: false } }

/* ── Image presentation — hero / fan / count default ─────────────────── */

const PRESENTATION_BASE: RichCardBaseProps = {
  title: 'My summer collection',
  subtitle: 'Three new looks, styled and ready.',
  actions: [secondaryLink('View collection', 'tr.ee/briesummer')],
}

/**
 * The `imagePresentation` knob: `hero` (one prominent image), `fan` (2–3 fanned
 * thumbnails), and the count-derived default when the knob is omitted (≤1 →
 * hero, ≥2 → fan). Shown on both surfaces.
 */
export const ImagePresentation: StoryFn = () => (
  <Table>
    <TableHead
      columns={[
        'hero (1)',
        'fan (2)',
        'fan (3)',
        'default — 1 img',
        'default — 2 imgs',
      ]}
    />
    <tbody>
      {(['Received', 'Sent'] as const).map((side) => {
        const Card = RichCard[side]
        return (
          <tr key={side}>
            <RowLabel>{side}</RowLabel>
            <Cell>
              <Card
                {...PRESENTATION_BASE}
                images={[IMAGE]}
                imagePresentation="hero"
              />
            </Cell>
            <Cell>
              <Card
                {...PRESENTATION_BASE}
                images={[IMAGE, IMAGE_2]}
                imagePresentation="fan"
              />
            </Cell>
            <Cell>
              <Card
                {...PRESENTATION_BASE}
                images={[IMAGE, IMAGE_2, IMAGE_3]}
                imagePresentation="fan"
              />
            </Cell>
            <Cell>
              <Card {...PRESENTATION_BASE} images={[IMAGE]} />
            </Cell>
            <Cell>
              <Card {...PRESENTATION_BASE} images={[IMAGE, IMAGE_2]} />
            </Cell>
          </tr>
        )
      })}
    </tbody>
  </Table>
)
ImagePresentation.parameters = { chromatic: { disableSnapshot: false } }

/* ── Footer layout — variant drives stacked vs inline ────────────────── */

const FOOTER_BASE: RichCardBaseProps = {
  title: 'A note from Brie',
  subtitle: 'Pick how you’d like to keep in touch.',
  images: [IMAGE],
  imagePresentation: 'hero',
}

/**
 * Footer emphasis + layout. A card has **one primary (main) action**; any
 * further action is `secondary`, so the hierarchy is carried by emphasis
 * (filled main vs subtle alternate) — not by two identical buttons. The first
 * action's variant also drives layout: `primary` → stacked full-width;
 * `secondary` → inline compact row.
 *
 * The last column is the anti-pattern (two primaries) — no hierarchy; author
 * `primary + secondary` instead.
 */
export const FooterLayout: StoryFn = () => (
  <Table>
    <TableHead
      columns={[
        'primary (main)',
        'secondary',
        'primary + secondary',
        'two primaries (avoid)',
      ]}
    />
    <tbody>
      {(['Received', 'Sent'] as const).map((side) => {
        const Card = RichCard[side]
        return (
          <tr key={side}>
            <RowLabel>{side}</RowLabel>
            <Cell>
              <Card
                {...FOOTER_BASE}
                actions={[primary('Set up welcome message')]}
              />
            </Cell>
            <Cell>
              <Card
                {...FOOTER_BASE}
                actions={[secondaryLink('Shop now', 'tr.ee/x')]}
              />
            </Cell>
            <Cell>
              <Card
                {...FOOTER_BASE}
                actions={[primary('Set up now'), secondary('Maybe later')]}
              />
            </Cell>
            <Cell>
              <Card
                {...FOOTER_BASE}
                actions={[primary('Set up now'), primary('Maybe later')]}
              />
            </Cell>
          </tr>
        )
      })}
    </tbody>
  </Table>
)
FooterLayout.parameters = { chromatic: { disableSnapshot: false } }

/* ── Accent chin — hero-only derivation + gate ───────────────────────── */

const ACCENTS: Array<{ label: string; accentColor?: string }> = [
  { label: '#7008E7', accentColor: '#7008E7' },
  { label: '#738883', accentColor: '#738883' },
  { label: 'none', accentColor: undefined },
  { label: 'malformed', accentColor: 'rebeccapurple' },
]

/**
 * Accent derivation reuses LinkAttachment's `useChinPalette`: a validated hex
 * paints the card + tail surface, hue kept and lightness swapped to a WCAG-safe
 * stop; `none` / malformed keep the plain fill. It is gated to a single on-
 * screen `hero` image — the bottom row shows a `fan` card ignoring the accent.
 */
export const AccentChin: StoryFn = () => (
  <Table>
    <TableHead columns={ACCENTS.map(({ label }) => label)} />
    <tbody>
      <tr>
        <RowLabel>Sent (last in run)</RowLabel>
        {ACCENTS.map(({ label, accentColor }) => (
          <Cell key={label}>
            <RichCard.Sent {...SINGLE_LINK} accentColor={accentColor} />
          </Cell>
        ))}
      </tr>
      <tr>
        <RowLabel>Received</RowLabel>
        {ACCENTS.map(({ label, accentColor }) => (
          <Cell key={label}>
            <RichCard.Received {...SINGLE_LINK} accentColor={accentColor} />
          </Cell>
        ))}
      </tr>
      <tr>
        <RowLabel>fan — accent ignored</RowLabel>
        {ACCENTS.map(({ label, accentColor }) => (
          <Cell key={label}>
            <RichCard.Sent {...COLLECTION} accentColor={accentColor} />
          </Cell>
        ))}
      </tr>
    </tbody>
  </Table>
)
AccentChin.parameters = { chromatic: { disableSnapshot: false } }

/* ── Content edges — clamps, missing pieces, tailless ────────────────── */

const LONG_TITLE =
  'Set up your welcome message so every new follower gets greeted the moment they say hello'
const LONG_SUBTITLE =
  'Thanks for reaching out! This is the kind of longer prose body an official message carries — it runs well past a single line and should wrap up to the clamp instead of clipping like a link preview, then trail off with an ellipsis once it reaches the limit.'

/**
 * Edge cases: a title past two lines (clamps at 2), a long prose subtitle
 * (clamps at the 3-line default), an image-less card (chin only, content-sized),
 * a title-only card, an action-only card, and a mid-run card (no bubble tail).
 */
export const ContentEdges: StoryFn = () => (
  <Table>
    <TableHead
      columns={[
        'long title',
        'long subtitle',
        'no image',
        'title only',
        'mid-run (no tail)',
      ]}
    />
    <tbody>
      {(['Received', 'Sent'] as const).map((side) => {
        const Card = RichCard[side]
        return (
          <tr key={side}>
            <RowLabel>{side}</RowLabel>
            <Cell>
              <Card
                {...OFFICIAL_WELCOME}
                title={LONG_TITLE}
                subtitle="Short subtitle."
              />
            </Cell>
            <Cell>
              <Card {...OFFICIAL_WELCOME} subtitle={LONG_SUBTITLE} />
            </Cell>
            <Cell>
              <Card
                title="No image, just copy"
                subtitle="An image-less rich card sizes to its content instead of the 250px box."
                actions={[primary('Got it')]}
              />
            </Cell>
            <Cell>
              <Card
                {...OFFICIAL_WELCOME}
                subtitle={undefined}
                actions={undefined}
              />
            </Cell>
            <Cell>
              <Card {...OFFICIAL_WELCOME} groupPosition="middle" />
            </Cell>
          </tr>
        )
      })}
    </tbody>
  </Table>
)
ContentEdges.parameters = { chromatic: { disableSnapshot: false } }
