import { type CSSProperties, type FC, useRef } from 'react';
import { useFormContext } from 'react-hook-form';

import { fromPairs } from 'lodash-es';
import useVirtualizer from '@material-hu/hooks/useVirtualizer';
import Box from '@material-hu/mui/Box';
import Stack from '@material-hu/mui/Stack';

import HuAccordion from '@material-hu/components/design-system/Accordion';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox';
import HuFormCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox/form';

import { useLokaliseTranslation } from 'src/utils/i18n';

import { type TwoFieldGroup } from 'src/components/AdvancedFilter/types';

const CHECKBOX_ROW_ESTIMATE = 24;
const ITEM_GAP_PX = 24;
const ROW_SIZE_ESTIMATE = CHECKBOX_ROW_ESTIMATE + ITEM_GAP_PX;
const MAX_VISIBLE_ROWS = 6;

const SELECT_ALL_ROW = { type: 'selectAll' } as const;

type ListRow = typeof SELECT_ALL_ROW | TwoFieldGroup['items'][number];

type VirtualRow = { index: number; start: number };

const getVirtualRowStyle = (
  virtualRow: VirtualRow,
  isLast: boolean,
): CSSProperties => ({
  position: 'absolute',
  top: 0,
  left: 0,
  width: '100%',
  transform: `translateY(${virtualRow.start}px)`,
  ...(isLast ? {} : { paddingBottom: ITEM_GAP_PX }),
});

type Props = {
  group: TwoFieldGroup;
  groupFieldName: string;
  parentExpanded: boolean;
  setParentExpanded: (expanded: boolean) => void;
  expandedGroup: boolean;
  setExpandedGroup: (expanded: string | null) => void;
};

/**
 * @deprecated Use the new GroupItems from @material-hu/components/composed-components/CollapsibleGroupSelector instead.
 */
const GroupItems: FC<Props> = props => {
  const {
    group,
    groupFieldName,
    parentExpanded,
    setParentExpanded,
    expandedGroup,
    setExpandedGroup,
  } = props;
  const { t } = useLokaliseTranslation('time_tracker');
  const parentForm = useFormContext();
  const formItems = parentForm.watch(groupFieldName);

  const selectedItems = group.items.filter(
    item => parentForm.getValues(groupFieldName)[item.value],
  );

  const itemsSelected = (selectedGroup: TwoFieldGroup) => {
    const totalItems = selectedGroup.items.length;
    return {
      all: selectedItems.length === totalItems,
      some: selectedItems.length > 0 && selectedItems.length < totalItems,
    };
  };

  const scrollElementRef = useRef<HTMLDivElement>(null);
  const items = expandedGroup ? group.items : [];
  const listData: ListRow[] =
    group.items.length > 1 ? [SELECT_ALL_ROW, ...items] : items;
  const listMaxHeight =
    Math.min(listData.length, MAX_VISIBLE_ROWS) * ROW_SIZE_ESTIMATE -
    ITEM_GAP_PX;

  const { virtualRows, rowVirtualizer } = useVirtualizer({
    scrollElementRef,
    registers: listData,
    virtualizerOptions: {
      count: listData.length,
      estimateSize: () => ROW_SIZE_ESTIMATE,
      getScrollElement: () => scrollElementRef.current,
      enabled: listData.length > 0,
    },
    withWindowScroll: false,
    hasNextPage: false,
    isFetchingNextPage: false,
    fetchNextPage: undefined,
  });

  return (
    <HuAccordion
      key={group.value}
      title={`${group.name} (${selectedItems.length}/${group.items.length})`}
      expanded={parentExpanded && expandedGroup}
      onChange={(_, expanded) => {
        setParentExpanded(expanded);
        setExpandedGroup(expanded ? group.name : null);
      }}
      elevation={0}
      sx={{
        borderRadius: ({ spacing }) => spacing(1),
        mb: 2,
        backgroundColor: ({ palette }) => palette.new.background.layout.default,
        '&:before': {
          backgroundColor: 'transparent',
        },
      }}
      customDetail={
        <HuCardContainer
          sx={{
            width: '100%',
          }}
        >
          {listData.length > 0 ? (
            <Stack
              ref={scrollElementRef}
              sx={{
                gap: 0,
                maxHeight: listMaxHeight,
                overflow: 'auto',
              }}
            >
              <Stack
                style={{
                  height: `${rowVirtualizer.getTotalSize()}px`,
                  width: '100%',
                  position: 'relative',
                }}
              >
                {virtualRows.map(virtualRow => {
                  const row = listData[virtualRow.index];
                  if (!row) return null;
                  const isLast = virtualRow.index === listData.length - 1;
                  const isSelectAll = 'type' in row && row.type === 'selectAll';

                  if (isSelectAll) {
                    return (
                      <Box
                        key="select-all"
                        data-index={virtualRow.index}
                        ref={rowVirtualizer.measureElement}
                        style={getVirtualRowStyle(virtualRow, isLast)}
                      >
                        <HuCheckbox
                          label={t('SELECT_ALL')}
                          onChange={() => {
                            const availableOptions = group.items.map(
                              o => o.value,
                            );
                            parentForm.setValue(groupFieldName, {
                              ...formItems,
                              ...fromPairs(
                                availableOptions.map(o => [
                                  o,
                                  !itemsSelected(group).all,
                                ]),
                              ),
                            });
                          }}
                          checked={itemsSelected(group).all}
                          indeterminate={itemsSelected(group).some}
                        />
                      </Box>
                    );
                  }

                  const item = row as TwoFieldGroup['items'][number];
                  return (
                    <Box
                      key={item.value}
                      data-index={virtualRow.index}
                      ref={rowVirtualizer.measureElement}
                      style={getVirtualRowStyle(virtualRow, isLast)}
                    >
                      <HuFormCheckbox
                        name={`${String(groupFieldName)}.${item.value}`}
                        checkBoxProps={{
                          label: item.label,
                        }}
                      />
                    </Box>
                  );
                })}
              </Stack>
            </Stack>
          ) : null}
        </HuCardContainer>
      }
      disableGutters
    />
  );
};

export default GroupItems;
