import React, { forwardRef, memo, useState } from 'react';

import { Chip } from '@cleartrip/ct-design-chip';
import { Box } from '@cleartrip/ct-design-box';
import { Container, ContainerRef } from '@cleartrip/ct-design-container';
import { Typography } from '@cleartrip/ct-design-typography';
import { useStyles } from '@cleartrip/ct-design-style-manager';
import useIsomorphicEffect from '@cleartrip/ct-design-use-isomorphic-effect';

import { ISingleSelectProps, SingleChipProps } from './type';
import { ChipOrientation } from './constants';
import { singleSelectChipStaticStyles } from './style';

interface ChipAtomsProps {
  data: SingleChipProps[];
  selectedChip: string | null;
  onClickCb: (chip: SingleChipProps) => () => void;
  chipStyleConfig?: ISingleSelectProps['styleConfig'] extends infer T
    ? T extends { chip?: infer C }
      ? C
      : never
    : never;
}

const ChipAtoms = memo(({ data, selectedChip, onClickCb, chipStyleConfig }: ChipAtomsProps) => {
  return (
    <>
      {data.map((item) => {
        const isSelected = item?.id === selectedChip;

        return (
          <Chip
            key={item?.id}
            id={item?.id}
            label={item?.label}
            onClick={onClickCb(item)}
            size='sm'
            isSelected={isSelected}
            styleConfig={{
              labelContainer: [singleSelectChipStaticStyles.chipLabelStyles],
              root: [singleSelectChipStaticStyles.chipRootStyles, singleSelectChipStaticStyles.chipBoxShadow],
              ...(chipStyleConfig || {}),
            }}
          />
        );
      })}
    </>
  );
});

ChipAtoms.displayName = 'ChipAtoms';

const SingleSelectChip = forwardRef<ContainerRef, ISingleSelectProps>(
  ({ onChange, data, orientation = ChipOrientation.row, selected = null, prompt, styleConfig = {} }, ref) => {
    const { hasError = false, Icon: promptIcon, message: promptMessage } = prompt || {};

    const {
      root: customRootStyles = [],
      chipContainer: chipContainerStyles = [],
      promptBox: promptBoxStyles = [],
      promptIconContainer: promptIconContainerStyles = [],
      promptMessageTypography: promptMessageTypographyStyles,
      chip: chipStyleConfig,
    } = styleConfig;

    const [selectedChip, setSelectedChip] = useState<string | null>(selected ?? null);

    useIsomorphicEffect(() => {
      if ((selected ?? null) !== selectedChip) {
        setSelectedChip(selected ?? null);
      }
    }, [selected]);

    const onClickCb = (chip: SingleChipProps) => () => {
      const { id } = chip ?? {};

      if (selectedChip !== id) {
        setSelectedChip(id);
        onChange?.(id);
      }
    };

    const dynamicStyles = useStyles(
      () => ({
        chipWrapper: {
          flexDirection: orientation === ChipOrientation.row ? 'row' : 'column',
        },
      }),
      [orientation],
    );

    return (
      <Container ref={ref} styleConfig={{ root: [...(customRootStyles || [])] }}>
        <Container
          styleConfig={{
            root: [singleSelectChipStaticStyles.chipWrapper, dynamicStyles.chipWrapper, ...chipContainerStyles],
          }}
        >
          <ChipAtoms data={data} selectedChip={selectedChip} onClickCb={onClickCb} chipStyleConfig={chipStyleConfig} />
        </Container>

        {(promptIcon || promptMessage) && (
          <Box
            boxSize='pico'
            horizontal
            styleConfig={{
              root: [singleSelectChipStaticStyles.promptBoxStyles, ...(promptBoxStyles || [])],
            }}
          >
            {promptIcon && (
              <Container
                styleConfig={{
                  root: [singleSelectChipStaticStyles.promptIconStyles, ...promptIconContainerStyles],
                }}
              >
                {promptIcon}
              </Container>
            )}
            {promptMessage && (
              <Typography
                variant='B3'
                color={hasError ? 'warning' : 'success'}
                styleConfig={promptMessageTypographyStyles}
              >
                {promptMessage}
              </Typography>
            )}
          </Box>
        )}
      </Container>
    );
  },
);

SingleSelectChip.displayName = 'SingleSelectChip';

export default memo(SingleSelectChip);
