import { Box, Flex } from '@chakra-ui/react'
import * as React from 'react'

type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
  ? Acc[number]
  : Enumerate<N, [...Acc, Acc['length']]>

type Range<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>

type ColorSchema = 'green' | 'blue' | 'purple' | 'yellow' | 'orange' | 'white' | 'red'

interface ICustomProgressProps {
  value: Range<1, 101>
  colorSchema?: ColorSchema
}

const mapColorSchemaToStyles = (color: ColorSchema) => {
  switch (color) {
    case 'green':
      return {
        bg: 'linear-gradient(90deg, rgba(122, 235, 228, 0.314), rgb(122, 235, 228))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(122, 235, 228) 0%, rgba(122, 235, 228, 0.004) 75.52%, rgba(122, 235, 228, 0.004) 88.54%, rgba(122, 235, 228, 0) 100%)',
        dotBg: 'rgba(122, 235, 228, 0.44)',
        border: 'rgba(122, 235, 228, 0.44)',
      }
    case 'blue':
      return {
        bg: 'linear-gradient(90deg, rgba(69, 143, 255, 0.314), rgb(69, 143, 255))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(69, 143, 255) 0%, rgba(69, 143, 255, 0.004) 75.52%, rgba(69, 143, 255, 0.004) 88.54%, rgba(69, 143, 255, 0) 100%)',
        dotBg: 'rgba(69, 143, 255, 0.44)',
        border: '1px solid rgb(69, 143, 255)',
      }
    case 'yellow':
      return {
        bg: 'linear-gradient(90deg, rgba(215, 255, 103, 0.314), rgb(215, 255, 103))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(215, 255, 103) 0%, rgba(215, 255, 103, 0.004) 75.52%, rgba(215, 255, 103, 0.004) 88.54%, rgba(215, 255, 103, 0) 100%)',
        dotBg: 'rgba(215, 255, 103, 0.44)',
        border: '1px solid rgb(215, 255, 103)',
      }
    case 'purple':
      return {
        bg: 'linear-gradient(90deg, rgba(123, 97, 255, 0.314), rgb(123, 97, 255))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(123, 97, 255) 0%, rgba(123, 97, 255, 0.004) 75.52%, rgba(123, 97, 255, 0.004) 88.54%, rgba(123, 97, 255, 0) 100%)',
        dotBg: 'rgb(123, 97, 255, 0.44)',
        border: '1px solid rgb(123, 97, 255)',
      }
    case 'orange':
      return {
        bg: 'linear-gradient(90deg, rgba(237, 137, 54, 0.314), rgb(237, 137, 54))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(237, 137, 54) 0%, rgba(123, 97, 255, 0.004) 75.52%, rgba(123, 97, 255, 0.004) 88.54%, rgba(123, 97, 255, 0) 100%)',
        dotBg: 'rgb(237, 137, 54, 0.44)',
        border: '1px solid rgb(237, 137, 54)',
      }
    case 'red':
      return {
        bg: 'linear-gradient(90deg, rgba(245, 101, 101, 0.314), rgb(245, 101, 101))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(245, 101, 101) 0%, rgba(123, 97, 255, 0.004) 75.52%, rgba(123, 97, 255, 0.004) 88.54%, rgba(123, 97, 255, 0) 100%)',
        dotBg: 'rgb(245, 101, 101, 0.44)',
        border: '1px solid rgb(245, 101, 101)',
      }

    default:
      return {
        bg: 'linear-gradient(90deg, rgba(247, 250, 252, 0.314), rgb(247, 250, 252))',
        progressBg:
          'radial-gradient(50% 50% at 100% 50%, rgb(247, 250, 252) 0%, rgba(247, 250, 252, 0.004) 75.52%, rgba(247, 250, 252, 0.004) 88.54%, rgba(247, 250, 252, 0) 100%)',
        dotBg: 'rgba(247, 250, 252, 0.44)',
        border: 'rgba(247, 250, 252, 0.44)',
      }
  }
}

const CustomProgress: React.FunctionComponent<ICustomProgressProps> = ({ value, colorSchema = 'blue' }) => {
  const styles = mapColorSchemaToStyles(colorSchema)

  return (
    <Flex
      border={'1px dashed rgb(64, 64, 65)'}
      rounded={'40px'}
      w={'full'}
      pos={'relative'}
      flexDir={'column'}
      flexWrap={'nowrap'}
      justify={'flex-start'}
      align={'stretch'}
      p={'3px'}
      m={0}
      minW={'unset'}
      maxW={'full'}
      gap={0}
      h={'auto'}
      minH={'auto'}
      bg={'transparent'}
      float={'none'}
    >
      <Box w={`${value}%`} bg={styles.bg} rounded={'40px'} h={'5px'} pos={'relative'} />
      <Box
        w={`${value}%`}
        bg={styles.bg}
        rounded={'40px'}
        _before={{
          display: value < 40 ? 'none' : 'block',
          content: "''",
          background: styles.progressBg,
          width: '100%',
          right: `calc(${100 - value}%)`,
          transform: 'translateY(-25%)',
          borderRadius: '40px',
          height: '180%',
          position: 'absolute',
          top: '0px',
        }}
      >
        <Flex
          w={'full'}
          pos={'relative'}
          flexDir={'column'}
          flexWrap={'nowrap'}
          justify={'flex-start'}
          align={'stretch'}
          p={0}
          m={0}
          minW={'unset'}
          maxW={'full'}
          gap={0}
          h={'auto'}
          minH={'auto'}
          bg={'transparent'}
          float={'none'}
        >
          <Box
            right="-0.3125rem"
            z-index="100"
            background={styles.dotBg}
            width="0.8125rem"
            height="0.8125rem"
            position="absolute"
            top="-9.5px"
            border={styles.border}
            transform="rotate(45deg)"
            backdropFilter="blur(4px)"
            padding="0.15625rem"
            boxSizing="border-box"
            _before={{
              backdropFilter: 'blur(4px)',
              content: "''",
              display: 'block',
              width: '100%',
              height: '100%',
              margin: 'auto',
              borderRadius: '50%',
              border: styles.border,
              boxSizing: 'border-box',
            }}
            _after={{
              backdropFilter: 'blur(4px)',
              position: 'absolute',
              width: '100%',
              height: '100%',
              display: 'block',
              content: "''",
              zIndex: '1',
              top: '0px',
              left: '0px',
            }}
          />
        </Flex>
      </Box>
    </Flex>
  )
}

export default CustomProgress
