import { CopyButton, Tooltip, Box, Button, Card, Flex, Menu, Modal, Typography, Anchor } from '@tidbcloud/uikit'
import { IconChevronDown } from '@tidbcloud/uikit/icons'
import { useEffect, useRef, useState } from 'react'

import { downloadOas, authorizeOas } from 'dbaas/services/dataservice'

import { useDataApiContext } from '../../context'
import { showErrorMsg } from '../../helpers'
import { OPEN_API_SPEC_TYPE } from '../../types'
import { downFile } from '../../utils'

export const AuthModal = ({ cb, onClose, opened }: { cb: () => void; onClose: () => void; opened: boolean }) => {
  const [authOpened, setAuthOpened] = useState(opened)
  const [authing, setAuthing] = useState(false)
  const { orgId, projectId, editApp, appList, appListRef, setAppList, setEditApp } = useDataApiContext()

  useEffect(() => {
    setAuthOpened(opened)
  }, [opened])

  const authOas = async () => {
    setAuthing(true)
    try {
      await authorizeOas(orgId, projectId, `${editApp?.id}`)

      setAuthOpened(false)
      setAuthing(false)
      const list = appList.slice()
      const app = list.find((item) => item.id === editApp?.id)
      if (app) {
        app.oas_authorized = true
        setAppList(list)
        appListRef.current = list
      }
      if (editApp) {
        setEditApp({
          ...editApp,
          oas_authorized: true
        })
      }

      cb()
    } catch (e) {
      setAuthing(false)
      showErrorMsg(e, true)
    }
  }

  return (
    <Modal
      centered
      title="Authorization Request"
      opened={authOpened}
      onClose={() => {
        setAuthOpened(false)
        onClose()
      }}
    >
      <Typography>
        Generation of OpenAPI Specification requires accesss to tables metadata stored in `information_schema.tables`,
        would you like to authorize?
      </Typography>
      <Flex justify="flex-end" mt={24} gap={24}>
        <Button
          variant="default"
          onClick={() => {
            setAuthOpened(false)
            onClose()
          }}
          data-mp-event="mp-decline-1691461016702"
        >
          Decline
        </Button>

        <Button loading={authing} onClick={authOas} data-mp-event="mp-authorize-1691461016703">
          Authorize
        </Button>
      </Flex>
    </Modal>
  )
}

const OpenApi = () => {
  const { orgId, projectId, editApp } = useDataApiContext()
  const [authOpened, setAuthOpened] = useState(false)
  const type = useRef<OPEN_API_SPEC_TYPE>(OPEN_API_SPEC_TYPE.JSON)
  const [downloading, setDownloading] = useState(false)

  const downloadSepc = async () => {
    setDownloading(true)
    try {
      const data = await downloadOas(
        orgId,
        projectId,
        `${editApp?.id}`,
        {
          format: type.current
        },
        {
          responseType: 'arraybuffer'
        }
      )

      const name = editApp?.app_name
        .split(' ')
        .filter((i) => i)
        .map((i) => `${i[0].toUpperCase()}${i.slice(1)}`)
        .join('_')

      await downFile(data as any as ArrayBuffer, `${name}_OpenAPI.${type.current}`)
      setDownloading(false)
    } catch (e) {
      showErrorMsg(e, true)
      setDownloading(false)
    }
  }

  const downloadHandler = (selectType: OPEN_API_SPEC_TYPE) => {
    type.current = selectType
    if (!editApp?.oas_authorized) {
      setAuthOpened(true)
    } else {
      downloadSepc()
    }
  }

  return (
    <Card
      p={24}
      my={24}
      sx={() => ({
        overflow: 'initial'
      })}
    >
      <Flex justify="space-between" align="top">
        <Box sx={{ whiteSpace: 'break-spaces' }}>
          <Typography variant="title-md" mb={4}>
            API Specification
          </Typography>
          <Typography variant="body-md" component="span">
            You can download specifications about your endpoints. The specifications follow the OpenAPI Specification
            format{editApp?.app_type !== 'chat2query' && ', and only contain the deployed endpoints'}. For further usage
            of the downloaded docs, please refer to the{' '}
            <Anchor
              c="peacock.7"
              fw={400}
              target="_blank"
              href="https://docs.pingcap.com/tidbcloud/data-service-oas-with-nextjs"
            >
              documentation
            </Anchor>
            .
          </Typography>
        </Box>
        <Flex gap={16}>
          <CopyButton value={editApp?.open_api_link ?? ''} timeout={1000}>
            {({ copied, copy }) => (
              <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="top">
                <Button variant="default" size="xs" onClick={copy}>
                  Copy Link
                </Button>
              </Tooltip>
            )}
          </CopyButton>
          <Menu width={120}>
            <Menu.Target>
              <Button variant="default" size="xs" loading={downloading} data-mp-event="mp--1691461016707">
                Download
                <IconChevronDown size={16} />
              </Button>
            </Menu.Target>
            <Menu.Dropdown>
              <Menu.Item onClick={() => downloadHandler(OPEN_API_SPEC_TYPE.JSON)}>JSON</Menu.Item>
              {editApp?.app_type !== 'chat2query' && (
                <Menu.Item onClick={() => downloadHandler(OPEN_API_SPEC_TYPE.YAML)}>YAML</Menu.Item>
              )}
            </Menu.Dropdown>
          </Menu>
        </Flex>
      </Flex>

      <AuthModal
        cb={() => {
          downloadSepc()
          setAuthOpened(false)
        }}
        opened={authOpened}
        onClose={() => setAuthOpened(false)}
      />
    </Card>
  )
}

export default OpenApi
