import { useState, useRef, useEffect, ReactNode } from 'react'
import {
  Container,
  Stack,
  Text,
  ThemeIcon,
  Box,
  rem,
  Collapse,
  useMantineTheme,
  Flex,
} from '@pikku/mantine/core'
import { asI18n } from '@pikku/react'

export interface ExpandableStep {
  title: string
  icon: ReactNode
  content: () => ReactNode
}

interface ExpandableStepsProps {
  steps: ExpandableStep[]
  defaultExpanded?: number[]
  singleExpand?: boolean
  containerSize?: string
  showTitle?: boolean
  title?: string
}

export function ExpandableSteps({
  steps,
  defaultExpanded = [0],
  singleExpand = true,
  containerSize = 'xl',
  showTitle = false,
  title,
}: ExpandableStepsProps) {
  const theme = useMantineTheme()
  const [expandedSteps, setExpandedSteps] = useState(() => new Set(defaultExpanded))
  const contentRefs = useRef<(HTMLDivElement | null)[]>([])
  const [heights, setHeights] = useState<number[]>([])

  const CIRCLE_SIZE = 38
  const GAP = 8

  useEffect(() => {
    const observers: ResizeObserver[] = []

    contentRefs.current.forEach((el, i) => {
      if (!el) return
      const observer = new ResizeObserver(() => {
        setHeights((prev) => {
          const copy = [...prev]
          copy[i] = el.offsetHeight
          return copy
        })
      })
      observer.observe(el)
      observers.push(observer)
    })

    return () => {
      observers.forEach((observer) => observer.disconnect())
    }
  }, [])

  const calculateLineHeight = (index: number): number => {
    if (index === steps.length - 1) return 0
    const contentHeight = heights[index] ?? 0
    return contentHeight + GAP * 2
  }

  const toggleStep = (index: number) => {
    if (singleExpand) {
      setExpandedSteps(() => new Set([index]))
    } else {
      setExpandedSteps((prev) => {
        const newSet = new Set(prev)
        if (newSet.has(index)) {
          newSet.delete(index)
        } else {
          newSet.add(index)
        }
        return newSet
      })
    }
  }

  return (
    <Container size='xl' py="xl" mt="xl">
      <Stack
        gap="lg"
        mt="xl"
        w="100%"
        maw={{ base: rem(300), md: rem(800) }}
        mx="auto"
      >
        {showTitle && title && (
          <Text fz="xxll" fw={700} ta='center' mb='xl'>
            {asI18n(title)}
          </Text>
        )}

        {steps.map((step, index) => {
          const isActive = expandedSteps.has(index)
          const lineHeight =
            isActive && index !== steps.length - 1
              ? calculateLineHeight(index)
              : 0

          return (
            <Box
              key={step.title}
              pos="relative"
              display="flex"
              pl={{ base: 0, md: 30 }}
              mb={8}
              mih={40}
              c={isActive ? theme.colors.primary[6] : theme.colors.gray[9]}
              style={{ cursor: 'pointer' }}
            >
              <Box
                w={CIRCLE_SIZE}
                pos="relative"
                display="flex"
                style={{
                  flexDirection: 'column',
                  alignItems: 'center',
                  userSelect: 'none',
                }}
              >
                <Box
                  w={CIRCLE_SIZE}
                  h={CIRCLE_SIZE}
                  bg="white"
                  c={
                    isActive ? theme.colors.primary[6] : theme.colors.gray[9]
                  }
                  style={{
                    borderRadius: '50%',
                    border: `2px solid ${theme.colors.gray[4]}`,
                    fontSize: rem(16),
                    fontWeight: 700,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    cursor: 'pointer',
                    transform: `translateY(${rem(4)})`,
                    zIndex: 2,
                  }}
                  onClick={() => toggleStep(index)}
                >
                  {index + 1}
                </Box>

                {lineHeight > 0 && (
                  <Box
                    w={2}
                    h={lineHeight}
                    bg={`${theme.colors.gray[4]}`}
                    mt={GAP}
                    mb={GAP}
                    style={{
                      transition:
                        'height 300ms cubic-bezier(.4,2,.6,1), background-color 250ms ease',
                    }}
                  />
                )}
              </Box>

              <Box flex={1} me={10} onClick={() => toggleStep(index)}>
                <Flex
                  align="flex-start"
                  gap="xs"
                  style={{ wordBreak: 'break-word' }}
                  mb={6}
                >
                  <ThemeIcon
                    size={44}
                    variant="transparent"
                    color={isActive ? 'primary' : `${theme.colors.gray[8]}`}
                    radius="xl"
                    style={{ flexShrink: 0 }}
                  >
                    {step.icon}
                  </ThemeIcon>
                  <Text
                    fw={700}
                    fz={25}
                    style={{
                      whiteSpace: 'normal',
                      wordBreak: 'break-word',
                      flexGrow: 1,
                      flexShrink: 1,
                    }}
                    ta={'left'}
                    c={isActive ? 'primary' : `${theme.colors.gray[8]}`}
                  >
                    {asI18n(step.title)}
                  </Text>
                </Flex>

                <Collapse in={isActive} transitionDuration={250}>
                  <Container
                    ref={(el) => {
                      contentRefs.current[index] = el
                    }}
                    id={`step-${index}-content`}
                    p={0}
                    mb="md"
                  >
                    {step.content()}
                  </Container>
                </Collapse>
              </Box>
            </Box>
          )
        })}
      </Stack>
    </Container>
  )
}
