import { Modal, Loader, Flex, Anchor, ActionIcon, Alert, Typography, Select } from '@tidbcloud/uikit'
import { CodeBlock } from '@tidbcloud/uikit/biz'
import { IconAlertCircle } from '@tidbcloud/uikit/icons'
import { useEffect, useState } from 'react'

import { getEndpointCodeExample } from 'dbaas/services/dataservice'
import { getErrorMessage } from 'dbaas/services/errorCodes'

import { useDataApiContext } from '../context'
import { EndPoint } from '../types'

import Deploy from './Deploy'

type ExampleItem = {
  type: string
  code: string
}
type Example = {
  test: ExampleItem[]
  prod: ExampleItem[]
}

const CodeExample: React.FC<
  React.PropsWithChildren<{ endpoint: EndPoint; open: boolean; onClose: () => void; source?: string }>
> = ({ endpoint, open, onClose }) => {
  const { orgId, projectId, appList, editEndpointRef, setEditEndpoint, setEditApp, setDataappOpenedTab } =
    useDataApiContext()
  const [activeTab, setActiveTab] = useState<string | null>(editEndpointRef.current?.is_online ? 'prod' : 'test')
  const [opened, setOpened] = useState(false)
  const [loading, setLoading] = useState(false)
  const [examples, setExamples] = useState<Example>({
    test: [],
    prod: []
  })
  const [val, setVal] = useState('')
  const [err, setErr] = useState('')
  const [authType, setAuthType] = useState('digest')
  const [language, setLanguage] = useState('curl')

  useEffect(() => {
    if (open) {
      const activeEnv = editEndpointRef.current?.is_online ? 'prod' : 'test'
      setActiveTab(activeEnv)
      setLanguage('curl')
      getExample('', activeEnv, 'curl')
    }
  }, [open])

  const getExample = async (auth?: string, defaultActive?: string, selectLanguage?: string) => {
    setLoading(true)
    setOpened(true)
    try {
      const res: any = await getEndpointCodeExample(orgId, projectId, `${endpoint?.dataappp_id}`, `${endpoint?.id}`, {
        auth_type: auth || authType || 'digest',
        language: selectLanguage || language || 'curl'
      })
      setLoading(false)
      if (res.code !== 200) {
        throw new Error(res.message)
      } else {
        setExamples(res.data)
        resetOptions(defaultActive || activeTab || 'test', res.data)
      }
    } catch (e) {
      setLoading(false)
      setErr(getErrorMessage(e))
    }
  }

  const resetOptions = (key = 'test', data: Example) => {
    let options = (data[key] || []).map((example: ExampleItem) => {
      return {
        label: example.type,
        value: example.code
      }
    })

    setVal(options.length && options[0].value)
  }

  const closeModal = () => {
    setOpened(false)
    onClose()
  }

  return (
    <Modal size={660} title="Code Example" trapFocus={false} opened={opened} centered onClose={closeModal}>
      <Flex mb={16} gap={16}>
        <Select
          value={activeTab}
          placeholder="Test Enviroment"
          data={[
            { label: 'Test Environment', value: 'test' },
            { label: 'Online Environment', value: 'prod' }
          ]}
          onChange={(env) => {
            setActiveTab(env)
            resetOptions(env ?? '', examples)
          }}
        />

        <Select
          defaultValue="digest"
          data={[
            { label: 'Basic Authentication', value: 'basic' },
            { label: 'Digest Authentication', value: 'digest' }
          ]}
          onChange={(auth) => {
            setAuthType(auth || 'digest')
            getExample(auth || 'digest')
          }}
        />

        <Select
          defaultValue="curl"
          data={[
            { label: 'CURL', value: 'curl' },
            { label: 'JavaScript', value: 'js' }
          ]}
          onChange={(lang) => {
            setLanguage(lang || 'curl')
            getExample(undefined, undefined, lang || 'curl')
          }}
        />
      </Flex>

      {loading ? (
        <Loader />
      ) : (
        <>
          {err ? (
            <Typography variant="body-lg" c="red">
              {err}
            </Typography>
          ) : (
            <>
              {activeTab === 'prod' && !examples?.prod?.length ? (
                <Alert color="yellow">
                  <Flex align="flex-start">
                    <ActionIcon color="yellow.9" mt={-2}>
                      <IconAlertCircle size={14} strokeWidth={2} />
                    </ActionIcon>
                    <Typography>
                      This endpoint remains inaccessible in the online environment until deployed.{' '}
                      <Deploy
                        endpoint={endpoint}
                        variant="subtle"
                        text="Deploy Now"
                        isCompact={true}
                        showMsg={false}
                        onError={closeModal}
                        onSuccess={() => {
                          getExample()
                        }}
                      />
                    </Typography>
                  </Flex>
                </Alert>
              ) : (
                <CodeBlock>{(val || '').replaceAll('\\n', '\n').replaceAll('\t', '  ')}</CodeBlock>
              )}
            </>
          )}
        </>
      )}

      {activeTab === 'prod' && !examples?.prod?.length ? null : (
        <Typography variant="body-md" mt={16}>
          Accessing the endpoint requires an API Key.
          <Anchor
            mx={4}
            fw={600}
            onClick={() => {
              const appIndex = appList.findIndex((app) => `${app.id}` === `${endpoint?.dataappp_id}`)
              if (appIndex !== -1) {
                setEditEndpoint(null)
                editEndpointRef.current = null
                setEditApp(appList[appIndex])
                closeModal()

                setDataappOpenedTab('Settings')
              }
            }}
          >
            Create an API Key
          </Anchor>
          if you don't have it yet.
        </Typography>
      )}
    </Modal>
  )
}

export default CodeExample
