import React, { createContext, Children, useContext, useMemo } from 'react';
import { Separator } from '@radix-ui/themes';
import { Flex } from '../atoms/flex';
import { Avatar } from '../atoms/avatar';
import { CheckIcon } from '../icon';
import { Typo } from '../atoms/typo';

interface StepState extends Pick<StepperProps, 'direction'> {
  active: boolean;
  completed: boolean;
  index: number;
}

const StepContext = createContext<StepState>({
  active: false,
  completed: false,
  index: 0,
});

interface StepperProps {
  // 활성화된 스텝 인덱스. 0부터 시작
  activeStep?: number;
  children?: React.ReactNode | React.ReactNode[];
  width?: string;
  maxWidth?: string;
  minWidth?: string;
  /** icon과 children의 배치 방향. 기본 값 vertical */
  direction?: 'horizontal' | 'vertical';
}

function Root(props: StepperProps): React.ReactNode {
  const {
    activeStep = 0,
    children,
    width,
    minWidth,
    maxWidth,
    direction = 'vertical',
  } = props;

  return (
    <Flex
      gap="3"
      style={{
        width,
        minWidth,
        maxWidth,
      }}
    >
      {Children.map(children, (child, index) => {
        return (
          <StepContext.Provider
            value={{
              active: index === activeStep,
              completed: index < activeStep,
              index,
              direction,
            }}
          >
            {child}
          </StepContext.Provider>
        );
      })}
    </Flex>
  );
}

interface StepProps {
  children?: React.ReactNode;
  /** 아이콘 커스텀 필요시 사용 */
  Icon?: (args: { completed: boolean; active: boolean }) => React.ReactNode;
}

function Step(props: StepProps): React.ReactNode {
  const { Icon, children } = props;
  const {
    active,
    completed,
    index,
    direction = 'vertical',
  } = useContext(StepContext);

  const connector =
    index > 0 ? (
      <Separator
        style={{
          width: `calc(100% - 40px)`,
          position: 'absolute',
          top: 16,
          right: `calc(50% + 26px)`,
        }}
      />
    ) : null;

  const InnerStep = useMemo<(props: StepProps) => React.ReactNode>(() => {
    if (active) {
      return ActiveStep;
    }
    if (completed) {
      return CompleteStep;
    }
    return IncompleteStep;
  }, [completed, active]);

  return (
    <Flex
      align="center"
      direction={direction === 'horizontal' ? 'row' : 'column'}
      gap="4"
      position="relative"
      style={{ flex: 1 }}
    >
      {connector}
      <InnerStep Icon={Icon}>{children}</InnerStep>
    </Flex>
  );
}

function CompleteStep(props: StepProps): React.ReactNode {
  const { Icon, children } = props;
  const { completed, active } = useContext(StepContext);
  const background = 'var(--accent-a4)';
  const border = '1px solid var(--accent-7)';
  const color = 'var(--accent-contrast)';

  return (
    <>
      {Icon ? (
        <Icon active={active} completed={completed} />
      ) : (
        <Avatar
          fallback={<CheckIcon fill={color} height={16} width={16} />}
          radius="full"
          size="medium"
          style={{
            border,
            background,
          }}
        />
      )}
      <Typo align="center" variant="caption">
        {children}
      </Typo>
    </>
  );
}

function IncompleteStep(props: StepProps): React.ReactNode {
  const { Icon, children } = props;
  const { completed, active, index } = useContext(StepContext);
  const background = 'var(--gray-5)';
  const color = 'var(--gray-a11)';
  return (
    <>
      {Icon ? (
        <Icon active={active} completed={completed} />
      ) : (
        <Avatar
          fallback={<Typo style={{ color }}>{index + 1}</Typo>}
          radius="full"
          size="medium"
          style={{
            background,
          }}
        />
      )}
      <Typo align="center" style={{ color }} variant="caption">
        {children}
      </Typo>
    </>
  );
}

function ActiveStep(props: StepProps): React.ReactNode {
  const { Icon, children } = props;
  const { completed, active, index } = useContext(StepContext);
  const background = 'var(--accent-10)';
  const color = 'var(--accent-contrast)';

  return (
    <>
      {Icon ? (
        <Icon active={active} completed={completed} />
      ) : (
        <Avatar
          fallback={
            <Typo style={{ color }} weight="bold">
              {index + 1}
            </Typo>
          }
          radius="full"
          size="medium"
          style={{ background }}
        />
      )}
      <Typo align="center" variant="caption" weight="bold">
        {children}
      </Typo>
    </>
  );
}

export const Stepper = {
  Root,
  Step,
};
