import { Box, Skeleton, Typography, Flex } from '@tidbcloud/uikit'
import { createStyles } from '@tidbcloud/uikit/emotion'
import { useState } from 'react'

import { useGetDataappDeployDiff, useGetDataappDeployLogDiff } from 'dbaas/services/dataservice'
import { EntitySnapshotDiff } from 'dbaas/services/dataservice/interface'

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

const useStyles = createStyles(() => {
  return {
    Pre: {
      margin: 0
    }
  }
})

export const TextDiff = ({ value }: { value: string }) => {
  const values = value.split('\n')
  const { classes } = useStyles()

  const getColor = (text: string) => {
    if (text.startsWith('---') || text.startsWith('+++')) {
      return {
        color: 'carbon.6'
      }
    }

    if (text.startsWith('+')) {
      return {
        color: 'green',
        label: '+',
        value: text.substring(1),
        bg: true
      }
    }

    if (text.startsWith('-')) {
      return {
        color: 'red',
        label: '-',
        value: text.substring(1),
        bg: true
      }
    }

    if (text.startsWith('@@')) {
      return {
        color: 'peacock',
        bg: true
      }
    }

    return {
      color: 'gray'
    }
  }

  return (
    <Box>
      {values.map((v, i) => {
        const { color, label, value, bg } = getColor(v)
        return (
          <Box component="pre" className={classes.Pre} key={i}>
            <Flex lh="20px">
              <Typography
                variant="body-md"
                w={32}
                bg={bg ? `${color}.3` : 'transparent'}
                sx={{ textAlign: 'center', flexShrink: 0 }}
                c={`${color}.9`}
              >
                {label}
              </Typography>
              <Typography
                px={8}
                variant="body-md"
                c={color.includes('.') ? color : `${color}.9`}
                bg={bg ? `${color}.1` : 'transparent'}
                sx={{ flex: 1 }}
              >
                {value ?? v}
              </Typography>
            </Flex>
          </Box>
        )
      })}
    </Box>
  )
}

const Diff = ({
  logId,
  type,
  maxHeight,
  endpointId
}: {
  logId?: string
  type?: string
  maxHeight?: string | number
  endpointId?: string
}) => {
  const { orgId, projectId, editApp, editEndpoint, dataappDeployConfig } = useDataApiContext()
  const [diffDetail, setDiffDetail] = useState<EntitySnapshotDiff | undefined>()

  const { isFetching } = useGetDataappDeployDiff(
    orgId,
    projectId,
    `${editApp?.id || editEndpoint?.dataappp_id}`,
    {
      diff_type: 'text',
      endpoint_id: endpointId
    },
    {
      query: {
        enabled: !logId && !type && !!orgId && !!projectId && (!!editApp?.id || !!editEndpoint?.dataappp_id),
        refetchInterval: false,
        refetchOnWindowFocus: false,
        onSuccess: (data) => {
          setDiffDetail(data?.data)
        }
      }
    }
  )

  const { isFetching: isFetchingDetail } = useGetDataappDeployLogDiff(
    orgId,
    projectId,
    `${editApp?.id || editEndpoint?.dataappp_id}`,
    `${logId || ''}`,
    {
      diff_type: 'text',
      sence: type || 'redeploy'
    },
    {
      query: {
        enabled: !!logId && !!type && !!orgId && !!projectId && (!!editApp?.id || !!editEndpoint?.dataappp_id),
        refetchInterval: false,
        refetchOnWindowFocus: false,
        onSuccess: (data) => {
          setDiffDetail(data?.data)
        }
      }
    }
  )

  if (!dataappDeployConfig?.enable_ui_drafts) {
    return null
  }

  return (
    <>
      {isFetchingDetail || isFetching ? (
        <>
          <Skeleton height={16} radius="xl" />
          <Skeleton height={16} mt={8} radius="xl" />
          <Skeleton height={16} mt={8} radius="xl" />
        </>
      ) : (
        <>
          {diffDetail?.has_diff ? (
            <Box
              sx={(theme) => ({
                padding: '16px 0',
                border: `1px solid ${theme.colors.carbon[5]}`,
                borderRadius: theme.defaultRadius,
                maxHeight: maxHeight || '50vh',
                overflow: 'auto',
                scrollbarWidth: 'thin'
              })}
            >
              {diffDetail?.text_diff && <TextDiff value={diffDetail?.text_diff} />}
            </Box>
          ) : (
            <Typography
              variant="body-lg"
              sx={() => ({
                textAlign: 'center',
                padding: '50px 0'
              })}
            >
              no diff against online version
            </Typography>
          )}
        </>
      )}
    </>
  )
}

export default Diff
