import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router'
import { HttpStatusCode } from '@solidjs/start'
import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js'
import { FourOuFourView } from '~/components/Views/FourOuFour'
import { Loading } from '~/components/_shared/Loading'
import { gaIdentity } from '~/config'
import { useLocalize } from '~/context/localize'
import { getShout } from '~/graphql/api/public'
import type { Author, Reaction, Shout, Topic } from '~/graphql/schema/core.gen'
import { initGA, loadGAScript } from '~/utils/ga'
import { descFromBody, keywordsFromTopics } from '~/utils/meta'
import { FullArticle } from '../../components/Article/FullArticle'
import { PageLayout } from '../../components/_shared/PageLayout'
import { ReactionsProvider } from '../../context/reactions'
import AuthorPage, { AuthorPageProps } from '../author/[slug]/[...tab]'
import TopicPage, { TopicPageProps } from '../topic/[slug]/[...tab]'

const fetchShout = async (slug: string): Promise<Shout | undefined> => {
  if (slug.startsWith('@')) return
  const shoutLoader = getShout({ slug })
  const result = await shoutLoader()
  return result
}

export const route: RouteDefinition = {
  load: async ({ params }) => ({
    article: await fetchShout(params.slug)
  })
}

export type ArticlePageProps = {
  article?: Shout
  comments?: Reaction[]
  votes?: Reaction[]
  author?: Author
}

export type SlugPageProps = {
  article?: Shout
  comments?: Reaction[]
  votes?: Reaction[]
  author?: Author
  topics: Topic[]
}

export default function ArticlePage(props: RouteSectionProps<SlugPageProps>) {
  if (props.params.slug.startsWith('@')) {
    console.debug('[routes] [slug]/[...tab] starts with @, render as author page')
    const patchedProps = {
      ...props,
      params: {
        ...props.params,
        slug: props.params.slug.slice(1, props.params.slug.length)
      }
    } as RouteSectionProps<AuthorPageProps>
    return <AuthorPage {...patchedProps} />
  }

  if (props.params.slug.startsWith('!')) {
    console.debug('[routes] [slug]/[...tab] starts with !, render as topic page')
    const patchedProps = {
      ...props,
      params: {
        ...props.params,
        slug: props.params.slug.slice(1, props.params.slug.length)
      }
    } as RouteSectionProps<TopicPageProps>
    return <TopicPage {...patchedProps} />
  }

  function ArticlePage(props: RouteSectionProps<ArticlePageProps>) {
    const loc = useLocation()
    const { t } = useLocalize()
    const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug)))

    onMount(async () => {
      if (gaIdentity && data()?.id) {
        try {
          await loadGAScript(gaIdentity)
          initGA(gaIdentity)
        } catch (error) {
          console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error)
        }
      }
    })

    createEffect(
      on(
        data,
        (a?: Shout) => {
          if (!a?.id) return
          window?.gtag?.('event', 'page_view', {
            page_title: a.title,
            page_location: window?.location.href || '',
            page_path: loc.pathname
          })
        },
        { defer: true }
      )
    )

    return (
      <ErrorBoundary fallback={() => <HttpStatusCode code={500} />}>
        <Suspense fallback={<Loading />}>
          <Show
            when={data()?.id}
            fallback={
              <PageLayout isHeaderFixed={false} hideFooter={true} title={t('Nothing is here')}>
                <FourOuFourView />
                <HttpStatusCode code={404} />
              </PageLayout>
            }
          >
            <PageLayout
              title={`${t('Discours')}${data()?.title ? ' :: ' : ''}${data()?.title || ''}`}
              desc={descFromBody(data()?.body || '')}
              keywords={keywordsFromTopics(data()?.topics as { title: string }[])}
              headerTitle={data()?.title || ''}
              slug={data()?.slug}
              cover={data()?.cover || ''}
            >
              <ReactionsProvider>
                <FullArticle article={data() as Shout} />
              </ReactionsProvider>
            </PageLayout>
          </Show>
        </Suspense>
      </ErrorBoundary>
    )
  }
  return <ArticlePage {...props} />
}
