import { useEffect } from 'react'

import fs from 'fs'

import matter from 'gray-matter'
import { MDXRemote } from 'next-mdx-remote'
import { serialize } from 'next-mdx-remote/serialize'
import components from '~/components/index'
import { getAllDocs } from '~/lib/docs'

import ReactMarkdown from 'react-markdown'

// @ts-ignore
import jsTypeSpec from '~/../../spec/enrichments/tsdoc_v2/combined.json'
// @ts-ignore
import examples from '~/../../spec/examples/examples.yml' assert { type: 'yml' }
// @ts-expect-error
import jsSpec from '~/../../spec/supabase_js_v2_temp_new_shape.yml' assert { type: 'yml' }

import { IconDatabase, Tabs } from 'ui'
import CodeBlock from '~/components/CodeBlock/CodeBlock'

import { useRouter } from 'next/router'
import { extractTsDocNode, generateParameters } from '~/lib/refGenerator/helpers'
import { ComesFrom } from '~/components/ComesFrom'
import Param from '~/components/Params'
import Options from '~/components/Options'
import RefSubLayout from '~/layouts/ref/RefSubLayout'

export default function JSReference(props) {
  const router = useRouter()
  const slug = router.query.slug[0]

  // When user lands on a url like http://supabase.com/docs/reference/javascript/sign-up
  // find the #sign-up element and scroll to that
  useEffect(() => {
    if (document && slug !== 'start') {
      document.querySelector(`#${slug}`).scrollIntoView()
    }
  })

  return (
    <RefSubLayout>
      {jsSpec.functions.map((item, itemIndex) => {
        const hasTsRef = item['$ref'] || null
        const tsDefinition = hasTsRef && extractTsDocNode(hasTsRef, jsTypeSpec)
        const parameters = hasTsRef ? generateParameters(tsDefinition) : ''

        const functionMarkdownContent = props?.docs[itemIndex]?.content
        const shortText = hasTsRef ? tsDefinition.signatures[0].comment.shortText : ''

        return (
          <>
            <RefSubLayout.Section
              key={item.id}
              title={
                examples.functions[itemIndex].title ??
                examples.functions[itemIndex].id ??
                item.name ??
                item.id
              }
              id={item.id}
            >
              <RefSubLayout.Details>
                <>
                  <header className={['mb-16'].join(' ')}>
                    {shortText && (
                      <>
                        <p
                          className="text-sm text-scale-1100"
                          dangerouslySetInnerHTML={{ __html: shortText }}
                        ></p>
                      </>
                    )}
                  </header>

                  {item.description && (
                    <div className="prose">
                      <p className="text-sm">{item.description}</p>
                    </div>
                  )}
                  {functionMarkdownContent && (
                    <div className="prose">
                      <MDXRemote {...functionMarkdownContent} components={components} />
                    </div>
                  )}
                  {item.notes && (
                    <div className="prose">
                      <ReactMarkdown className="text-sm">{item.notes}</ReactMarkdown>
                    </div>
                  )}
                  {/* // parameters */}
                  {parameters && (
                    <div className="not-prose mt-12">
                      <h5 className="mb-3 text-base">Parameters</h5>
                      <ul className="">
                        {parameters.map((param) => {
                          // grab override params from yaml file
                          const overrideParams = item.overrideParams

                          // params from the yaml file can override the params from parameters if it matches the name
                          const overide = overrideParams?.filter((x) => {
                            return param.name === x.name
                          })

                          const paramItem = overide?.length > 0 ? overide[0] : param

                          return (
                            <Param {...paramItem}>
                              {paramItem.subContent && (
                                <div className="mt-3">
                                  <Options>
                                    {param.subContent.map((param) => {
                                      return <Options.Option {...param} />
                                    })}
                                  </Options>
                                </div>
                              )}
                            </Param>
                          )
                        })}
                      </ul>
                    </div>
                  )}
                </>
              </RefSubLayout.Details>
              <RefSubLayout.Examples>
                {item.examples && (
                  <>
                    {' '}
                    <ComesFrom
                      className="mb-5"
                      link="https://github.com/supabase/supabase/blob/master/spec/supabase_js_v2.yml"
                      text="supabase_js_v2"
                    />
                    <Tabs
                      defaultActiveId={item.examples[0].id}
                      size="small"
                      type="underlined"
                      scrollable
                    >
                      {item.examples &&
                        item.examples.map((example, exampleIndex) => {
                          const exampleString = `
import { createClient } from '@supabase/supabase-js'

// Create a single supabase client for interacting with your database
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')
`
                          const currentExampleId = example.id
                          const staticExample = item.examples[exampleIndex]

                          const response = staticExample.response
                          const sql = staticExample?.data?.sql
                          const tables = staticExample?.data?.tables

                          return (
                            <Tabs.Panel id={example.id} label={example.name}>
                              {tables &&
                                tables.length > 0 &&
                                tables.map((table) => {
                                  return (
                                    <div className="bg-scale-300 border rounded prose max-w-none">
                                      <div className="bg-scale-200 px-5 py-2">
                                        <div className="flex gap-2 items-center">
                                          <div className="text-brand-900">
                                            <IconDatabase size={16} />
                                          </div>
                                          <h5 className="text-xs text-scale-1200">{table.name}</h5>
                                        </div>
                                      </div>
                                    </div>
                                  )
                                })}
                              {sql && (
                                <CodeBlock
                                  className="useless-code-block-class"
                                  language="sql"
                                  hideLineNumbers={true}
                                >
                                  {sql}
                                </CodeBlock>
                              )}
                              <CodeBlock
                                className="useless-code-block-class"
                                language="js"
                                hideLineNumbers={true}
                              >
                                {exampleString +
                                  (example.code &&
                                    example.code
                                      .replace('```', '')
                                      .replace('js', '')
                                      .replace('```', ''))}
                              </CodeBlock>
                              {response && (
                                <>
                                  <ComesFrom
                                    className="mb-5 mt-5"
                                    link="https://github.com/supabase/supabase/pull/10095/files#diff-c514c66b77772b9e3d9a5403c136ee52dfeaaeacb1d8138ea85ce35ee64e5006"
                                    text="examples.yml"
                                  />
                                  <CodeBlock
                                    className="useless-code-block-class"
                                    language="json"
                                    hideLineNumbers={true}
                                  >
                                    {response}
                                  </CodeBlock>
                                </>
                              )}
                            </Tabs.Panel>
                          )
                        })}
                    </Tabs>
                  </>
                )}
              </RefSubLayout.Examples>
            </RefSubLayout.Section>
          </>
        )
      })}
    </RefSubLayout>
  )
}

export async function getStaticProps({ params }: { params: { slug: string[] } }) {
  const pages = jsSpec.functions.map((x) => x.id)

  /**
   * Read all the markdown files that might have
   *  - custom text
   *  - call outs
   *  - important notes regarding implementation
   */
  const allMarkdownDocs = await Promise.all(
    pages.map(async (x, i) => {
      const pathName = `docs/ref/js/${x}.mdx`

      function checkFileExists(x) {
        // console.log('checking this ', x)
        if (fs.existsSync(x)) {
          return true
        } else {
          return false
        }
      }

      const markdownExists = checkFileExists(pathName)

      console.log(x, 'markdownExists', markdownExists)

      const fileContents = markdownExists ? fs.readFileSync(pathName, 'utf8') : ''
      const { data, content } = matter(fileContents)

      return {
        id: x,
        title: x,
        // ...content,
        meta: data,
        content: content ? await serialize(content || '') : null,
      }
    })
  )

  return {
    props: {
      docs: allMarkdownDocs,
    },
  }
}

export function getStaticPaths() {
  let docs = getAllDocs()

  return {
    paths: docs.map(() => {
      return {
        params: {
          slug: docs.map((d) => d.slug),
        },
      }
    }),
    fallback: 'blocking',
  }
}
