import React, { JSXElementConstructor } from 'react'

import ArticleBody from '../body-components/ArticleBody'
import LiveBlogBody from '../body-components/LiveBlogBody'
import PodcastBody from '../body-components/PodcastBody'
import ContentPackageBody from '../body-components/ContentPackageBody'

import type { ArticleQuery } from '@financial-times/cp-content-pipeline-client'
import type { RichTextComponentMapRecord } from '../RichText'

export type BodyComponentMapRecord = Partial<
  Record<
    | ArticleQuery['content']['__typename']
    // these are here for backwards compatibility:
    | 'live-blog-body'
    | 'article-body'
    | 'podcast-body'
    | 'content-package-body'
    // this will be used for any content type without a default or override body
    | 'fallback',
    // using any here, no easy way to make a type that works for all the potential renderers
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    JSXElementConstructor<any>
  >
>

const contentTypeLegacyOverrideMap: Partial<
  Record<
    ArticleQuery['content']['__typename'],
    Exclude<
      keyof BodyComponentMapRecord,
      ArticleQuery['content']['__typename'] | 'fallback'
    >
  >
> = {
  Audio: 'podcast-body',
  LiveBlogPackage: 'live-blog-body',
  ContentPackage: 'content-package-body',
}

const defaultBodyComponents = {
  Audio: PodcastBody,
  LiveBlogPackage: LiveBlogBody,
  ContentPackage: ContentPackageBody,
  fallback: ArticleBody,
} satisfies BodyComponentMapRecord

export type BodyProps = {
  content: ArticleQuery['content']
  richTextComponents?: RichTextComponentMapRecord
  bodyComponents?: BodyComponentMapRecord
  [key: string]: unknown
}

const Body: React.FC<BodyProps> = ({
  content,
  bodyComponents,
  ...extraProps
}) => {
  if (!content?.body?.structured) {
    return null
  }

  const bodyComponentsWithOverrides = {
    ...defaultBodyComponents,
    ...bodyComponents,
  }

  const legacyOverrideKey =
    contentTypeLegacyOverrideMap[content.__typename] ?? 'article-body'
  const overrideComponent =
    legacyOverrideKey in bodyComponentsWithOverrides
      ? bodyComponentsWithOverrides[legacyOverrideKey]
      : bodyComponentsWithOverrides[content.__typename]

  const BodyComponent =
    overrideComponent ?? bodyComponentsWithOverrides.fallback ?? ArticleBody

  return <BodyComponent content={content} {...extraProps} />
}

export default Body
