import React from 'react'
import { LinkPreviewsManager, LinkPreviewsManagerState } from 'stream-chat'
import { useMessageComposer, useStateStore } from 'stream-chat-react'

import LinkAttachment from '../LinkAttachment'

const linkPreviewsManagerStateSelector = (state: LinkPreviewsManagerState) => ({
  linkPreviews: Array.from(state.previews.values()).filter(
    (preview) =>
      LinkPreviewsManager.previewIsLoaded(preview) ||
      LinkPreviewsManager.previewIsLoading(preview)
  ),
})

/**
 * The composer's staged link previews, rendered as `LinkAttachment.Composer`
 * cards.
 *
 * **The cards are deliberately dismiss-only — they do not navigate.**
 * `LinkAttachment.Composer` is the one card variant whose shell is never an
 * anchor or a button, and the hand-rolled card this replaced wrapped its whole
 * body in `<a href={og_scrape_url} target="_blank">` with the dismiss button
 * calling `preventDefault()` inside it. That shape is a touch hazard —
 * MES-1358 §7 Q7 raised it and deferred the call to MES-1349 — because a
 * mis-tap while composing opens a new tab mid-draft, and the dismiss button's
 * 44px hit halo (`Composer/Card.tsx`, `before:-inset-[10px]`) sits *inside*
 * that anchor, so enlarging the target for touch enlarges the navigation
 * trigger with it. A staged preview is a draft affordance rather than
 * content — its URL is still in the textarea the author just typed it into,
 * one tap away without leaving the thread.
 *
 * Nothing depended on the old behaviour: no test, story or analytics asserted
 * it here or in frontyard's parallel `ComposerLinkPreviewList`, whose own
 * tests cover text, dismiss and layout only. If a surface ever genuinely needs
 * activation, add an explicit prop to `ComposerCardProps` — do not re-wrap the
 * card in an anchor. (MES-1349)
 */
export const CustomLinkPreviewList = () => {
  const { linkPreviewsManager } = useMessageComposer()

  const { linkPreviews: stateLinkPreviews } = useStateStore(
    linkPreviewsManager.state,
    linkPreviewsManagerStateSelector
  )

  const handleDismiss = (url: string) => {
    linkPreviewsManager.dismissPreview(url)
  }

  const showLinkPreviews = stateLinkPreviews.length > 0

  if (!showLinkPreviews) return null

  return (
    // Layout contract: this list is NOT a scrollable or shrinkable region. It
    // used to be the composer's one squeezable box, giving way (min-h-0) and
    // scrolling on its own so the textarea row could stay pinned above the
    // keyboard. That cropped the preview to make room for the input, which read
    // as the preview being cut off; MES-1037 inverted it. The composer card
    // (`.central-container`) is now the single capped scroll container and this
    // list scrolls as one piece with the textarea inside it, so the preview
    // always keeps its full height and only the visible slice of it changes.
    // Do not reintroduce a nested scroller or a min-h-0 here.
    //
    // Horizontally the card does NOT shrink, deliberately. `CardShell` bakes
    // Figma's `w-[290px]` and there is exactly one width, in the toolkit
    // (MES-1349 and MES-1358 agreed consumers add no competing cap). Do not
    // "fix" a narrow viewport with `max-w-full` here or on the shell: the box is
    // `flex h-[250px] flex-col` with a `flex-1` hero and a title clamped to two
    // lines against a known width, so capping deforms it on every narrow
    // surface, in-thread Sent/Received included.
    //
    // Measured against the real class chain in headless Chromium:
    //
    //   chrome    = 32px (`CustomMessageInput`'s outer `p-4`)
    //             + 16px (this region's `px-2`)          = 48px
    //   card      = 290px  ->  floor = 290 + 48          = 338px viewport
    //
    //   viewport    320   360   375   393   430
    //   available   272   312   327   345   382
    //   delta       -18   +22   +37   +55   +92
    //
    // 393px is the design frame, and its 345px reproduces the frame's measured
    // `attachment-area` width, so the chrome arithmetic is corroborated. The
    // lowest named breakpoint is `xs: 359px`
    // (`@repo/tailwind-config/transitional-tokens.js:29-36`), which is *above*
    // the 338px floor — the card fits at every width the scale names. MES-1358's
    // `max-md:p-3` trims chrome 48px -> 40px and moves the floor to 330px, still
    // above 320px, so capping `CardShell` would be the only way to reach a 320px
    // viewport. That is the whole trade: deform every narrow surface, or leave
    // one sub-floor device class awkward.
    //
    // It is awkward, not broken. The card above sets only `overflow-y`, which
    // promotes the other axis, so its `overflow-x` computes to `auto` and it
    // scrolls sideways instead of spilling; at 320px the dismiss button's right
    // edge lands ~6px past the fold, reachable by scrolling. That residue
    // belongs to whoever owns the mobile layout contract, not to this component.
    <div className="messaging-link-preview-list flex flex-col items-stretch w-full gap-2">
      {stateLinkPreviews.map((linkPreview) => {
        // A LOADING preview has no `image_url` yet, so keying the layout off
        // the image alone rendered the skeleton as two bare text bars and then
        // snapped it open to the 250px featured box the instant the scrape
        // returned. Hold the hero's space for the duration instead — reserving
        // that space is what the skeleton is for.
        const isLoading = LinkPreviewsManager.previewIsLoading(linkPreview)

        return (
          <LinkAttachment.Composer
            key={linkPreview.og_scrape_url}
            title={linkPreview.title}
            url={linkPreview.og_scrape_url}
            thumbnailUrl={linkPreview.image_url}
            layout={isLoading || linkPreview.image_url ? 'featured' : 'classic'}
            status={isLoading ? 'loading' : 'ready'}
            onDismiss={() => handleDismiss(linkPreview.og_scrape_url)}
          />
        )
      })}
    </div>
  )
}
