import {useContent} from '../../hooks/content/useContent'
import {Content} from '../../types'

import {ContentMonitor} from './content-monitor'

interface BaseContentWrapperProps {
  /** A render function that receives the content data and loading state, and returns a React element. */
  children: ({
    content,
    loading,
  }: {
    content?: Content
    loading: boolean
  }) => React.JSX.Element | null
}

interface PublicIdContentWrapperProps extends BaseContentWrapperProps {
  publicId: string
  externalId?: never
}

interface ExternalIdContentWrapperProps extends BaseContentWrapperProps {
  externalId: string
  publicId?: never
}

type ContentWrapperProps =
  | PublicIdContentWrapperProps
  | ExternalIdContentWrapperProps

/**
 * The `ContentWrapper` component fetches and provides user-generated content data using a render function pattern. It accepts either a `publicId` or `externalId` to identify the content, and passes the resolved content along with loading state to a child render function.
 *
 * If `content` is not set (and `loading` is `false`), the ID was either not found or the content has been moderated and will not be shown. Users will always be able to see their own content.
 *
 * Use `ContentWrapper` when you need full control over how content is rendered. For a simpler image-specific wrapper, see `ImageContentWrapper`.
 *
 * > Note: Content rendered through `ContentWrapper` is wrapped in a `ContentMonitor` that allows users to report it for moderation.
 * @publicDocs
 */
// It's too messy in the docs to show the complete types here so we show a simplified version
export interface ContentWrapperPropsForDocs extends BaseContentWrapperProps {
  /** The public ID of the content item (use this OR externalId). */
  publicId?: string
  /** The external ID of the content item (use this OR publicId). */
  externalId?: string
}

export function ContentWrapper({
  publicId,
  externalId,
  children,
}: ContentWrapperProps) {
  const {content, loading} = useContent({
    identifiers: [{publicId, externalId}],
    skip: !publicId && !externalId,
  })

  const contentItem = content?.[0]

  if (loading || !contentItem) {
    return children({loading})
  }

  return (
    <ContentMonitor publicId={contentItem.publicId}>
      {children({content: contentItem, loading})}
    </ContentMonitor>
  )
}
