import {
  Divider,
  Drawer,
  Flex,
  Typography,
  Box,
  Button,
  Modal,
  notifier,
  CopyButton,
  Tooltip,
  ActionIcon,
  Prism,
  PrismProps
} from '@tidbcloud/uikit'
import { createStyles } from '@tidbcloud/uikit/emotion'
import {
  IconChevronRight,
  IconChevronLeft,
  IconPlus,
  IconDataService,
  IconChevronUp,
  IconChevronDown,
  IconCheck,
  IconCopy01
} from '@tidbcloud/uikit/icons'
import { useEffect, useState } from 'react'

import TimeComponent from 'dbaas/components/TimeComponent'
import { createEndpoint } from 'dbaas/services/dataservice'
import { DtoChat2QueryLog } from 'dbaas/services/dataservice/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'

import { useDataApiContext } from '../../context'
import { useCreateEndpCallbackHandler } from '../../helpers'
import { EndPoint } from '../../types'
import { Item } from '../AppLogs/LogDetail'

interface LogDetailProps {
  opened: boolean
  data: DtoChat2QueryLog | null
  index: number
  len: number
  close: () => void
  prev: () => void
  next: () => void
}

export const useLogDetailItem = createStyles(() => {
  return {
    LogItemContent: {
      overflow: 'hidden',
      textOverflow: 'ellipsis',
      display: '-webkit-box',
      WebkitBoxOrient: 'vertical',
      WebkitLineClamp: 10
    }
  }
})

interface DetailObjSectionProps {
  title: string
  content: string
  language?: string
  type?: string
  isActive?: boolean
}

const DetailObjSection: React.FC<React.PropsWithChildren<DetailObjSectionProps>> = ({
  title,
  content,
  language,
  type,
  isActive
}) => {
  const [isExpand, setIsExpand] = useState(false)

  if (type === 'create_data_summary') {
    return null
  }

  return (
    <Box
      my={16}
      p={12}
      sx={(t) => ({
        border: isActive ? `2px solid ${t.colors.blue[6]}` : `1px solid ${t.colors.carbon[5]}`,
        borderRadius: t.defaultRadius,
        backgroundColor: t.colors.carbon[2]
      })}
    >
      <Flex
        justify="space-between"
        sx={(t) => ({
          paddingBottom: 4,
          borderBottom: `1px solid ${t.colors.carbon[5]}`
        })}
      >
        <Typography variant="title-md">{title}</Typography>
        <Flex gap={16}>
          <Box
            sx={{ cursor: 'pointer' }}
            component={isExpand ? IconChevronDown : IconChevronUp}
            onClick={() => setIsExpand(!isExpand)}
          />
          <CopyButton value={content} timeout={2000}>
            {({ copied, copy }) => (
              <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
                <ActionIcon aria-label="Copy" variant="transparent" size="sm" onClick={copy}>
                  {copied ? <IconCheck size={14} /> : <IconCopy01 size={14} strokeWidth={2.5} onClick={copy} />}
                </ActionIcon>
              </Tooltip>
            )}
          </CopyButton>
        </Flex>
      </Flex>
      <Box mt={4}>
        {!!content && (
          <Prism
            noCopy
            language={(language ?? 'json') as PrismProps['language']}
            styles={{
              code: {
                backgroundColor: 'transparent !important',
                padding: 0,
                fontSize: 12,
                whiteSpace: 'normal',
                wordWrap: 'break-word'
              },
              scrollArea: {
                '& > div > div': {
                  display: 'block !important'
                }
              },
              lineContent: {
                padding: 0,
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                display: '-webkit-box',
                WebkitLineClamp: isExpand ? undefined : 3,
                WebkitBoxOrient: 'vertical'
              }
            }}
          >
            {content}
          </Prism>
        )}
      </Box>
    </Box>
  )
}

const LogDetail = ({ close, opened, data, index, len, prev, next }: LogDetailProps) => {
  const [chooseDataAppModalOpened, setChooseDataAppModalOpened] = useState(false)
  const [acitveSQLIndex, setAcitveSQLIndex] = useState(0)
  const [selectSql, setSelectSql] = useState('')

  useEffect(() => {
    if (!opened || !data) {
      setSelectSql('')
      return
    }

    if (data.output?.sub_tasks?.length) {
      setAcitveSQLIndex(0)
      setSelectSql(data.output.sub_tasks[0].sql ?? '')
    } else {
      setSelectSql(data.output?.sql ?? '')
    }
  }, [data?.request_id])

  return (
    <>
      <Drawer
        title={<Typography variant="title-lg"></Typography>}
        position="right"
        size={640}
        opened={opened}
        trapFocus={false}
        onClose={close}
        styles={(theme) => ({
          body: {
            height: 'calc(100% - 70px)'
          },
          header: {
            padding: '12px 24px',
            borderBottom: `1px solid ${theme.colors.carbon[3]}`
          }
        })}
      >
        <Flex
          direction="column"
          h="100%"
          sx={{
            overflow: 'hidden'
          }}
        >
          <Box
            sx={{
              flex: 1,
              overflowY: 'auto',
              padding: '0 24px'
            }}
          >
            <Item label="Request Id" content={data?.request_id} />
            <Item label="Type" content={data?.type} />
            <Item label="Status" content={data?.status} />
            <Item label="Date Time" content={<TimeComponent time={data?.log_time || ''} />} />
            <Item label="Start Time" content={<TimeComponent time={data?.start_at || ''} />} />
            <Item label="Response Time" content={data?.log_time || ''} />
            <Divider c="carbon.5" my="md" mx={-24} />

            <Item label="Session Id" content={data?.session_id} withCopy />
            <Item label="Data Summary Id" content={data?.data_summary_id} withCopy />
            <Item label="Cluster Id" content={data?.cluster_id} withCopy />
            <Item label="Database" content={data?.database || ''} withCopy />
            <Item
              label="Recalled Knowledge Data"
              content={JSON.stringify(data?.recalled_knowledge_data || '{}')}
              withCopy
            />
            <Item label="Used Token" content={data?.token_count} withCopy />
            <Divider c="carbon.5" my="md" mx={-24} />

            <DetailObjSection title="Input" content={JSON.stringify(data?.input)} type={data?.type} />
            <DetailObjSection title="Output" content={JSON.stringify(data?.output)} type={data?.type} />
            {data?.output?.sub_tasks?.length ? (
              <>
                {data.output.sub_tasks.map((task, idx) => (
                  <Box
                    onClick={() => {
                      setAcitveSQLIndex(idx)
                      setSelectSql(task.sql ?? '')
                    }}
                  >
                    <DetailObjSection
                      key={idx}
                      title="SQL"
                      content={task.sql ?? ''}
                      language="sql"
                      isActive={acitveSQLIndex === idx}
                      type={data?.type}
                    />
                  </Box>
                ))}
              </>
            ) : (
              <DetailObjSection title="SQL" content={data?.output?.sql ?? ''} language="sql" type={data?.type} />
            )}
          </Box>

          <Flex
            justify="space-between"
            py={16}
            px={24}
            sx={(t) => ({
              borderTop: `1px solid ${t.colors.carbon[3]}`
            })}
          >
            <Box>
              {index !== 0 && (
                <Button variant="default" size="sm" p={8} mr={16} w={40} onClick={prev}>
                  <IconChevronLeft size={20} />
                </Button>
              )}

              {index !== len - 1 && (
                <Button variant="default" size="sm" p={8} w={40} onClick={next}>
                  <IconChevronRight size={20} />
                </Button>
              )}
            </Box>
            {data?.type !== 'create_data_summary' && (
              <Button onClick={() => setChooseDataAppModalOpened(true)}>Convert SQL to Endpoint</Button>
            )}
          </Flex>
        </Flex>
      </Drawer>

      <CreateDataAppModal
        opened={chooseDataAppModalOpened}
        onClose={() => setChooseDataAppModalOpened(false)}
        logData={data}
        sql={selectSql}
      />
    </>
  )
}

interface CreateDataAppModalProps {
  opened: boolean
  logData: DtoChat2QueryLog | null
  sql: string
  onClose: () => void
}

const CreateDataAppModal = ({ opened, logData, sql, onClose }: CreateDataAppModalProps) => {
  const {
    appList,
    orgId,
    projectId,
    setEditEndpoint,
    editEndpointRef,
    setEditApp,
    setRenamedEndpoint,
    setCreateDataAppFromLogs
  } = useDataApiContext()
  const [chooseDataAppModalOpened, setChooseDataAppModalOpened] = useState(false)
  const { updateSelectData } = useCreateEndpCallbackHandler()

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

  useEffect(() => {
    if (!chooseDataAppModalOpened) {
      onClose()
    }
  }, [chooseDataAppModalOpened])

  const createDataApp = () => {
    setCreateDataAppFromLogs(true)
  }

  const createEndpointHandler = async (appId: string) => {
    const endpointDefaultParams = {
      name: '/untitled_endpoint',
      sql_template: `${logData?.database ? `USE ${logData.database};\n` : ''}${sql ?? ''}`,
      method: 'GET',
      settings: {
        row_limit: 1000,
        timeout: 30000
      },
      cluster_id: '0'
    }

    try {
      const res = await createEndpoint(orgId, projectId, appId, endpointDefaultParams)

      if (res.code === 200) {
        const ep = res.endpoint as EndPoint
        setEditEndpoint(ep)
        editEndpointRef.current = ep
        setEditApp(null)

        setRenamedEndpoint(ep)

        await updateSelectData(ep, true)
      }
    } catch (_e) {
      notifier.error(getErrorMessage(_e))
    }
  }

  return (
    <>
      <Modal
        title="Choose Data App"
        centered
        size={480}
        trapFocus={false}
        opened={chooseDataAppModalOpened}
        closeOnClickOutside={false}
        onClose={() => setChooseDataAppModalOpened(false)}
      >
        <Typography variant="body-lg">
          Choose an existing Data App or build a new data app to create endpoint.
        </Typography>
        <Flex
          px={24}
          py={16}
          mt={16}
          align="center"
          sx={(t) => ({
            border: `1px solid ${t.colors.carbon[6]}`,
            borderRadius: t.defaultRadius,
            cursor: 'pointer',
            '&:hover': {
              border: `1px solid ${t.colors.sky[7]}`
            }
          })}
          onClick={createDataApp}
        >
          <IconPlus size={24} />
          <Typography ml={16} variant="title-md">
            New Data App
          </Typography>
        </Flex>

        {appList
          .filter((app) => app.app_type === 'dataapi')
          .map((app) => (
            <Flex
              px={24}
              py={16}
              mt={16}
              align="center"
              sx={(t) => ({
                border: `1px solid ${t.colors.carbon[6]}`,
                borderRadius: t.defaultRadius,
                cursor: 'pointer',
                '&:hover': {
                  border: `1px solid ${t.colors.sky[7]}`
                }
              })}
              onClick={() => createEndpointHandler(app.id)}
            >
              <IconDataService size={24} />
              <Typography ml={16} variant="title-md">
                {app.app_name}
              </Typography>
            </Flex>
          ))}
      </Modal>
    </>
  )
}

export default LogDetail
