import type { Meta, StoryFn } from '@storybook/react'
import classNames from 'classnames'
import React from 'react'
import type { Attachment, LocalMessage } from 'stream-chat'

import {
  currentUserArgType,
  storyUsers,
  type StoryUser,
} from '../../stories/decorators/storyUser'

import StreamAttachmentMessage from './StreamAttachmentMessage'

/* ──────────────────────────────────────────────────────────────────
 * Stories for `StreamAttachmentMessage` — the toolkit-owned renderer
 * that `CustomMessage` uses for every generic Stream-attachment message
 * (link OG previews + image / video / audio / pdf / file media).
 *
 * Unlike `MessageAttachmentConversations.stories.tsx` — which hand-builds
 * `MessageAttachment.*` JSX directly — these stories feed raw Stream
 * `Attachment[]` shapes through `StreamAttachmentMessage` so they exercise
 * the mapping the component actually owns: ordered segment building,
 * Stream-attachment → `LinkAttachment` prop mapping, caption
 * de-duplication (including emoji preservation), and media clustering.
 *
 * The component owns the Stream bubble-wrapper markup. Stories only supply
 * the `.str-chat` / `.str-chat__message--me|other` / `.str-chat__li--single`
 * ancestry that Stream bubble chrome and the MES-1031 tails are scoped under.
 * ────────────────────────────────────────────────────────────────── */

const Bubbles: React.FC<{
  isMyMessage: boolean
  children: React.ReactNode
}> = ({ isMyMessage, children }) => (
  <div className="str-chat mx-auto max-w-2xl p-12">
    {/* Tail CSS is scoped to `.str-chat__li--single|--bottom`; bubble surface
        styles need `.str-chat__message--me|other`. */}
    <div className="str-chat__li str-chat__li--single">
      <div
        className={classNames(
          'str-chat__message str-chat__message-simple',
          isMyMessage
            ? 'str-chat__message--me str-chat__message-simple--me'
            : 'str-chat__message--other'
        )}
      >
        <div className="str-chat__message-inner">{children}</div>
      </div>
    </div>
  </div>
)

const Render = (attachments: Attachment[], text?: string): StoryFn<StoryArgs> =>
  function StreamAttachmentStory({ currentUser }) {
    const isMyMessage = currentUser.id === storyUsers.creator.id
    return (
      <Bubbles isMyMessage={isMyMessage}>
        <StreamAttachmentMessage
          groupPosition="single"
          isMyMessage={isMyMessage}
          message={{ attachments, text } as LocalMessage}
        />
      </Bubbles>
    )
  }

const HERO = 'https://picsum.photos/seed/og-hero/1200/630'
const PHOTO = (seed: string) => `https://picsum.photos/seed/${seed}/720/720`
const VIDEO_SRC = '/video-source.mp4'
const VIDEO_POSTER = '/video-thumbnail.jpg'
const PDF_SRC = 'https://www.w3.org/WAI/WCAG21/wcag21.pdf'

const linkAttachment = (overrides: Partial<Attachment> = {}): Attachment => ({
  type: 'link',
  og_scrape_url: 'https://linktr.ee/marketplace',
  title: 'Linktree Marketplace',
  text: 'Browse the best apps to customize your link in bio.',
  image_url: HERO,
  ...overrides,
})

const imageAttachment = (seed: string): Attachment => ({
  type: 'image',
  image_url: PHOTO(seed),
})

interface StoryArgs {
  currentUser: StoryUser
}

const meta: Meta<StoryArgs> = {
  title: 'CustomMessage/StreamAttachmentMessage',
  argTypes: currentUserArgType,
  args: { currentUser: storyUsers.creator },
  parameters: {
    layout: 'fullscreen',
    // Story render output embeds live React elements; pin source generation
    // to the static story code (matches MessageAttachmentConversations).
    docs: { source: { type: 'code' } },
  },
}
export default meta

/** Link share with an OG image → the featured card layout. */
export const LinkFeatured = Render([linkAttachment()])

/** Link share with no thumbnail → the classic (compact) card layout. */
export const LinkClassic = Render([
  linkAttachment({ image_url: undefined, thumb_url: undefined }),
])

/**
 * Link share with an emoji-only caption alongside the URL. The emoji is
 * real content, so the caption is preserved as a separate bubble beneath
 * the card (regression guard for the caption-dedup predicate).
 */
export const LinkWithEmojiCaption = Render(
  [linkAttachment({ og_scrape_url: 'https://mrdrnose.itch.io/votv' })],
  'https://mrdrnose.itch.io/votv 👽'
)

/**
 * Caption that is just the link URL → suppressed (the card already shows
 * the URL, so no duplicate text bubble).
 */
export const LinkWithUrlOnlyCaption = Render(
  [linkAttachment()],
  'https://linktr.ee/marketplace'
)

/** Single image attachment. */
export const SingleImage = Render([imageAttachment('single')])

/** Several images in one message → a clustered image bubble. */
export const ImageCluster = Render([
  imageAttachment('cluster-1'),
  imageAttachment('cluster-2'),
  imageAttachment('cluster-3'),
])

/** Video attachment (poster + play affordance). */
export const Video = Render([
  {
    type: 'video',
    asset_url: VIDEO_SRC,
    thumb_url: VIDEO_POSTER,
    mime_type: 'video/mp4',
    title: 'trailer.mp4',
  },
])

/** PDF document attachment with a caption. */
export const Pdf = Render(
  [
    {
      type: 'file',
      asset_url: PDF_SRC,
      mime_type: 'application/pdf',
      title: 'launch-checklist.pdf',
      file_size: 142_336,
    },
  ],
  'Section 4 has the details.'
)

/** Generic (non-PDF) file attachment with a download affordance. */
export const GenericFile = Render([
  {
    type: 'file',
    asset_url: 'https://cdn.example.com/brand-kit.zip',
    mime_type: 'application/zip',
    title: 'brand-kit.zip',
    file_size: 11_500_000,
  },
])

/**
 * Mixed message — media followed by a link share with a caption. Exercises
 * ordered-segment building across kinds: the image cluster renders first,
 * the link card second, and the caption attaches to the last bubble.
 */
export const MixedMediaAndLink = Render(
  [imageAttachment('mixed-1'), imageAttachment('mixed-2'), linkAttachment()],
  'Check these out 🔥'
)
