import React from 'react'
import { render } from '@testing-library/react'
import Body, { BodyComponentMapRecord } from '.'
import { ArticleQuery } from '@financial-times/cp-content-pipeline-client'

const baseContent: ArticleQuery['content'] = {
  __typename: 'Article',
  title: 'title',
  id: '00000000-0000-0000-0000-000000000000',
  url: 'https://www.ft.com/content/00000000-0000-0000-0000-000000000000',
  publishedDate: '2024-06-11T14:13:25.527Z',
  publishedTimestamp: 1718115205527,
  modifiedTimestamp: 1718115318431,
  publishReference: 'asdfghjkl',
  firstPublishedDate: '2024-06-11T14:13:25.527Z',
  annotations: [],
  body: {
    structured: {
      tree: {
        type: 'body',
        version: 1,
        children: [
          {
            type: 'paragraph',
            children: [
              {
                type: 'text',
                value: 'Lorem ipsum dolor sit amet',
              },
            ],
          },
        ],
      },
      references: [],
    },
  },
}

// these are the only content types we currently care about rendering bodies for
const typesToTest = [
  'Article',
  'Video',
  'Audio',
  'LiveBlogPackage',
  'ContentPackage',
] satisfies ArticleQuery['content']['__typename'][]

const extraContentForType = {
  Article: {},
  Audio: {
    __typename: 'Audio',
    media: [
      {
        mediaType: 'audio/mpeg',
        url: 'https://open.spotify.com/album/34a7B1mPM7RqlwsjPPmzEg?si=aHxMBJ1zRES6Z0iIrTrwBQ',
      },
    ],
  },
  ContentPackage: {
    __typename: 'ContentPackage',
    contains: [
      {
        id: '00000000-0000-0000-0000-000000000000',
        url: 'https://www.ft.com/content/00000000-0000-0000-0000-000000000000',
        type: 'article',
        title: 'teaser',
        publishedDate: '1970-01-01T00:00:00Z',
        firstPublishedDate: '1970-01-01T00:00:00Z',
        metaPrefixText: 'Analysis',
        indicators: {
          accessLevel: 'subscribed',
        },
        relativeUrl: '/content/00000000-0000-0000-0000-000000000000',
      },
    ],
  },
  LiveBlogPackage: {
    __typename: 'LiveBlogPackage',
    liveBlogPosts: [
      {
        ...baseContent,
        __typename: 'LiveBlogPost',
        title: 'live post 1',
        authors: [],
        indicators: {},
      },
    ],
  },
  Video: {
    __typename: 'Video',
  },
} satisfies Record<
  (typeof typesToTest)[number],
  Partial<ArticleQuery['content']>
>

const extraPropsForType: Partial<
  Record<ArticleQuery['content']['__typename'], Record<string, unknown>>
> = {
  LiveBlogPackage: {
    postTrackerConfig: {
      usePostTracker: false,
    },
  },
}

const legacyOverridesToTest = [
  ['Article', 'article-body'],
  ['LiveBlogPackage', 'live-blog-body'],
  ['ContentPackage', 'content-package-body'],
  ['Audio', 'podcast-body'],
] satisfies [
  ArticleQuery['content']['__typename'],
  keyof BodyComponentMapRecord
][]

describe('Body', () => {
  let mockDate: jest.SpyInstance
  let warnSpy: jest.SpyInstance
  beforeAll(() => {
    mockDate = jest
      .spyOn(Date.prototype, 'toLocaleString')
      .mockReturnValue('11/06/2024, 14:13:25')
    // suppress warning that LiveBlogPackage is using legacy componentWillReceiveProps in x-interaction component
    warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
  })
  afterAll(() => {
    mockDate.mockRestore()
    warnSpy.mockRestore()
  })
  describe('default renderers', () => {
    test.each(typesToTest)('renders default renderer for %s', (type) => {
      const { asFragment } = render(
        <Body
          content={{ ...baseContent, ...extraContentForType[type] }}
          {...(extraPropsForType[type] ?? {})}
        />
      )

      expect(asFragment()).toMatchSnapshot()
    })
  })

  describe('legacy override renderers', () => {
    test.each(legacyOverridesToTest)(
      'renders override renderer for %s',
      (type, overrideName) => {
        const { asFragment } = render(
          <Body
            content={{ ...baseContent, ...extraContentForType[type] }}
            {...(extraPropsForType[type] ?? {})}
            bodyComponents={{
              [overrideName]: ({
                content,
              }: {
                content: ArticleQuery['content']
              }) => <>body override {content.__typename}</>,
            }}
          />
        )

        expect(asFragment()).toMatchSnapshot()
      }
    )
  })

  describe('content type override renderers', () => {
    test.each(typesToTest)('renders override renderer for %s', (type) => {
      const { asFragment } = render(
        <Body
          content={{ ...baseContent, ...extraContentForType[type] }}
          {...(extraPropsForType[type] ?? {})}
          bodyComponents={{
            [type]: ({ content }: { content: ArticleQuery['content'] }) => (
              <>body override {content.__typename}</>
            ),
          }}
        />
      )

      expect(asFragment()).toMatchSnapshot()
    })
  })
})
