'use client'
import React, {PropsWithChildren, useMemo} from 'react'
import NextLink from 'next/link'
import Head from 'next/head'
import type {Folder, MdxFile, PageMapItem} from 'nextra'
import {useFSRoute} from 'nextra/hooks'
import {BaseStyles, Breadcrumbs, PageLayout, ThemeProvider} from '@primer/react'
import '@primer/primitives/dist/css/functional/themes/light.css'
import '@primer/primitives/dist/css/functional/themes/dark.css'
import {
  Animate,
  AnimationProvider,
  ButtonGroup,
  ThemeProvider as BrandThemeProvider,
  Button,
  Heading,
  Image,
  Stack,
  Text,
} from '@primer/react-brand'
import {Sidebar} from '../sidebar/Sidebar'
import {UnderlineNav} from '../underline-nav/UnderlineNav'

import '@primer/react-brand/fonts/fonts.css'
import '@primer/react-brand/lib/css/main.css'

import {normalizePages} from 'nextra/normalize-pages'
import {usePathname} from 'next/navigation'

import {useConfig} from '../../context/useConfig'

import {Header} from '../header/Header'
import {IndexCards} from '../index-cards/IndexCards'
import {useColorMode} from '../../context/color-modes/useColorMode'
import {SkipToMainContent} from '../skip-to-main-content/SkipToMainContent'
import {RelatedContentLinks} from '../related-content-links/RelatedContentLinks'
import {getRelatedPages} from '../related-content-links/getRelatedPages'
import {hasChildren} from '../../../helpers/hasChildren'
import {Footer} from '../footer/Footer'
import styles from './Theme.module.css'

const repoSrcPath = process.env.NEXT_PUBLIC_REPO_SRC_PATH || ''
const repoURL = process.env.NEXT_PUBLIC_REPO || ''

if (!repoURL) {
  console.warn(
    'NEXT_PUBLIC_REPO is not set. Edit the .env.local file to set the NEXT_PUBLIC_REPO environment variable.',
  )
}

export type ThemeProps = PropsWithChildren<{
  pageMap: PageMapItem[]
}>

export function Theme({pageMap, children}: ThemeProps) {
  const pathname = usePathname()
  const pathHasTrailingSlash = pathname.endsWith('/')

  const normalizedPages = normalizePages({
    list: pageMap,
    route: pathname,
  })

  const route = usePathname()

  const fsPath = useFSRoute()
  const {colorMode} = useColorMode()
  const {activePath, flatDocsDirectories} = useMemo(
    () =>
      normalizePages({
        list: pageMap,
        route: fsPath,
      }),
    [pageMap, fsPath],
  )

  const siteTitle = process.env.NEXT_PUBLIC_SITE_TITLE || 'Example Site'
  const {headerLinks} = useConfig()
  const activeHeaderLink = headerLinks.find(link => link.isActive)

  const isHomePage = route === '/'

  const activeFile = isHomePage
    ? undefined
    : (normalizedPages.flatDocsDirectories.find(
        item => `${item.route}${pathHasTrailingSlash ? '/' : ''}` === pathname,
      ) as MdxFile)

  const activeMetadata = activeFile?.frontMatter || {}
  const filePath = activeMetadata.filePath || ''
  const title = activeMetadata.title || ''

  const isIndexPage = /index\.mdx?$/.test(filePath) && !isHomePage && activeMetadata['show-tabs'] === undefined
  const data = !isHomePage && activePath[activePath.length - 2]
  const filteredTabData: MdxFile[] = data && hasChildren(data) ? ((data as Folder).children as MdxFile[]) : []

  const relatedLinks = getRelatedPages(route, activeMetadata, flatDocsDirectories)
  const disablePageAnimation = activeMetadata.options?.disablePageAnimation || false

  return (
    <>
      <BrandThemeProvider dir="ltr" colorMode={colorMode}>
        <ThemeProvider colorMode={colorMode}>
          <BaseStyles>
            <Head>
              <title>{title}</title>
              {activeMetadata.description && <meta name="description" content={activeMetadata.description} />}
              <meta property="og:type" content="website" />
              <meta property="og:title" content={title} />
              {activeMetadata.description && <meta property="og:description" content={activeMetadata.description} />}
              <meta property="og:image" content={activeMetadata.image || '/og-image.png'} />
              {/* X (Twitter) OG */}
              <meta name="twitter:card" content="summary_large_image" />
              <meta name="twitter:title" content={title} />
              {activeMetadata.description && <meta name="twitter:description" content={activeMetadata.description} />}
              <meta name="twitter:image" content={activeMetadata.image || '/og-image.png'} />
            </Head>

            <ContentWrapper disableAnimations={disablePageAnimation}>
              <div className={styles.StickyHeader}>
                <SkipToMainContent href="#main">Skip to main content</SkipToMainContent>
                <Header flatDocsDirectories={flatDocsDirectories} siteTitle={siteTitle} pageMap={pageMap} />
              </div>
              <PageLayout rowGap="none" columnGap="none" padding="none" containerWidth="full">
                <PageLayout.Pane
                  width="small"
                  sticky
                  offsetHeader={65}
                  padding="none"
                  position="start"
                  hidden={{narrow: true}}
                  divider="line"
                >
                  <aside aria-label={`${activeHeaderLink ? activeHeaderLink.title : siteTitle} sidebar`}>
                    <Sidebar pageMap={pageMap} />
                  </aside>
                </PageLayout.Pane>
                <PageLayout.Content padding="normal">
                  <div id="main">
                    <div style={!isHomePage ? {maxWidth: 1200, width: '100%', margin: '0 auto'} : undefined}>
                      <Stack direction="vertical" padding="none" gap="spacious">
                        {!isHomePage && (
                          <>
                            {activePath.length > 0 && (
                              <Breadcrumbs className={styles.BreadcrumbRoot}>
                                {(activeHeaderLink || siteTitle) && (
                                  <Breadcrumbs.Item as={NextLink} href="/">
                                    {activeHeaderLink ? activeHeaderLink.title : siteTitle}
                                  </Breadcrumbs.Item>
                                )}
                                {activePath
                                  .filter((item, index, array) => {
                                    const nextItem = array[index + 1]

                                    // Skip when current item is a folder followed by its index page
                                    // or when it is an index page with a tabbed navigation
                                    return !(
                                      (index < array.length - 1 &&
                                        nextItem.name === 'index' &&
                                        item.route === nextItem.route &&
                                        !nextItem.frontMatter['tab-label']) ||
                                      (item.name === 'index' && item.frontMatter['tab-label'])
                                    )
                                  })
                                  .map((item, index, visibleItems) => {
                                    const itemTitle = Array.isArray(item.children)
                                      ? item.children.find(child => child.name === 'index')?.frontMatter.title ||
                                        item.frontMatter['tab-label'] ||
                                        item.frontMatter.title ||
                                        item.title
                                      : item.frontMatter['tab-label'] || item.frontMatter.title || item.title

                                    const isLastItem = index === visibleItems.length - 1

                                    return (
                                      <Breadcrumbs.Item
                                        as={NextLink}
                                        key={item.name}
                                        href={item.route}
                                        selected={isLastItem}
                                        className={styles.BreadcrumbItem}
                                      >
                                        {itemTitle.replace(/-/g, ' ')}
                                      </Breadcrumbs.Item>
                                    )
                                  })}
                              </Breadcrumbs>
                            )}

                            <div>
                              <Stack direction="vertical" padding="none" gap={12} alignItems="flex-start">
                                {activeMetadata.title && (
                                  <Heading as="h1" size="3">
                                    {activeMetadata.title}
                                  </Heading>
                                )}
                                {activeMetadata.description && (
                                  <Text as="p" variant="muted" size="300">
                                    {activeMetadata.description}
                                  </Text>
                                )}
                                {activeMetadata.image && (
                                  <div className={styles.HeroImageWrapper}>
                                    <Image src={activeMetadata.image} alt={activeMetadata['image-alt']} />
                                  </div>
                                )}
                                {activeMetadata['action-1-text'] && (
                                  <div className={styles.ActionsWrapper}>
                                    <ButtonGroup>
                                      <Button as="a" href={activeMetadata['action-1-link']}>
                                        {activeMetadata['action-1-text']}
                                      </Button>
                                      {activeMetadata['action-2-text'] && (
                                        <Button as="a" variant="secondary" href={activeMetadata['action-2-link']}>
                                          {activeMetadata['action-2-text']}
                                        </Button>
                                      )}
                                    </ButtonGroup>
                                  </div>
                                )}
                              </Stack>
                            </div>
                            {activeMetadata['show-tabs'] && <UnderlineNav tabData={filteredTabData} />}
                          </>
                        )}
                        <article>
                          {isIndexPage ? (
                            <IndexCards folderData={flatDocsDirectories} route={route} />
                          ) : (
                            <>
                              <>{children}</>

                              {relatedLinks.length > 0 && (
                                <div className={styles.RelatedLinks}>
                                  <RelatedContentLinks links={relatedLinks} />
                                </div>
                              )}
                            </>
                          )}
                        </article>
                        <Footer filePath={filePath} repoURL={repoURL} repoSrcPath={repoSrcPath} />
                      </Stack>
                    </div>
                  </div>
                </PageLayout.Content>
              </PageLayout>
            </ContentWrapper>
          </BaseStyles>
        </ThemeProvider>
      </BrandThemeProvider>
    </>
  )
}

type ContentWrapperProps = PropsWithChildren<{
  disableAnimations?: boolean
}>

/**
 * The fade in animation masks the layout repainting issues.
 * That animation however, interferes with nested AnimationProviders so we need
 * to disable it for certain pages that use that.
 */
function ContentWrapper({children, disableAnimations}: ContentWrapperProps) {
  if (disableAnimations) {
    return <>{children}</>
  }

  return (
    <>
      <AnimationProvider runOnce visibilityOptions={1} autoStaggerChildren={false}>
        <Animate animate="fade-in">{children}</Animate>
      </AnimationProvider>
    </>
  )
}
