// The single wrap point for "long-press to save" on media. Wraps any media
// node (image, carousel slide, or video) in a native long-press context menu
// (zeego/context-menu → UIContextMenuInteraction on iOS, MenuView long-press on
// Android) with a "Save Photo/Video" action and an optional "Share" item.
//
// Drop it around an existing media node at any render site:
//   <SaveableMedia attachment={m}><Image …/></SaveableMedia>
//
// Wrap the LEAF media node (not an outer wrapper) so each carousel slide
// resolves to its own attachment, and so a sensitive shroud — which is a
// separate, unwrapped branch — can't be long-press-saved while hidden. Pass
// `enabled={false}` to opt a surface out entirely (zero overhead).
//
// The save itself lives in `lib/media/saveToPhotos`; this component owns only
// the menu UI and the toast/haptic feedback.

import { useCallback, useMemo } from 'react'
import { Share } from 'react-native'
import { useSaveMedia } from 'src/hooks/useSaveMedia'
import type { MediaAttachment } from 'src/lib/api-types'
import type { SaveMediaKind } from 'src/lib/media/saveToPhotos'
import * as ContextMenu from 'zeego/context-menu'

type Props = {
  /** Preferred: the attachment (kind + downloadable URL are derived from it). */
  attachment?: MediaAttachment
  /** Or pass a resolved uri+kind directly (the lightbox only knows the uri). */
  uri?: string
  kind?: SaveMediaKind
  /** When false, render children without the menu (e.g. shrouded sensitive). */
  enabled?: boolean
  /** When set, adds a "Share" item that shares this URL (the status permalink). */
  shareUrl?: string
  children: React.ReactNode
}

function kindOf(attachment?: MediaAttachment, fallback?: SaveMediaKind): SaveMediaKind {
  if (attachment) {
    return attachment.type === 'video' || attachment.type === 'gifv' ? 'video' : 'image'
  }
  return fallback ?? 'image'
}

// zeego renders two layout nodes around our child: the native menu host
// (ContextMenuView / MenuView) and the Trigger's inner <View>. Both shrink-wrap
// to their content, so SaveableMedia is layout-transparent only when its child
// is a self-sized leaf (explicit width + height). EVERY media leaf is now
// self-sized — feed images, album slides, VideoPlayer (computes its own
// { width, height }), and the lightbox ZoomableImage (shrink-wraps to its
// screen-sized image). So no flex hack is needed here: there is no slot-filling
// leaf left for the wrapper to compensate for. (An earlier `FILL` style forced
// the hosts to fill their slot to rescue a `flex:1` lightbox; that leaf is now
// self-sized, so forcing fill is both unnecessary and a regression risk on the
// native hosts — dropped.)

export default function SaveableMedia({
  attachment,
  uri,
  kind,
  enabled = true,
  shareUrl,
  children,
}: Props) {
  const save = useSaveMedia()
  const mediaKind = kindOf(attachment, kind)

  const onSave = useCallback(() => {
    save({ attachment, uri, kind }, mediaKind)
  }, [save, attachment, uri, kind, mediaKind])

  const onShare = useCallback(() => {
    if (!shareUrl) return
    Share.share({ message: shareUrl }).catch(() => {})
  }, [shareUrl])

  const content = useMemo(
    () => (
      <ContextMenu.Content>
        <ContextMenu.Item key="save" onSelect={onSave}>
          <ContextMenu.ItemTitle>
            {mediaKind === 'video' ? 'Save Video' : 'Save Photo'}
          </ContextMenu.ItemTitle>
          <ContextMenu.ItemIcon ios={{ name: 'square.and.arrow.down' }} />
        </ContextMenu.Item>
        {shareUrl ? (
          <ContextMenu.Item key="share" onSelect={onShare}>
            <ContextMenu.ItemTitle>Share</ContextMenu.ItemTitle>
            <ContextMenu.ItemIcon ios={{ name: 'square.and.arrow.up' }} />
          </ContextMenu.Item>
        ) : null}
      </ContextMenu.Content>
    ),
    [mediaKind, shareUrl, onSave, onShare]
  )

  if (!enabled) return <>{children}</>

  return (
    <ContextMenu.Root>
      <ContextMenu.Trigger>{children}</ContextMenu.Trigger>
      {content}
    </ContextMenu.Root>
  )
}
