import { useEffect } from "react";

import type {
  ComboboxItem,
  ComboboxLikeRenderOptionInput,
} from "@mantine/core";
import {
  Badge,
  Box,
  CheckIcon,
  Group,
  MultiSelect,
  Select,
  rem,
} from "@mantine/core";

import {
  useHitsPerPage,
  useRefinementList,
  useSortBy,
} from "react-instantsearch";

import { SourceLabelMap } from "@/constants";

const sortItems = [
  { value: "paragraph:time:desc", label: "Newest" },
  { value: "paragraph:time:asc", label: "Oldest" },
];
const hitsPerPageItems = [
  { value: 20, label: "20", default: true },
  { value: 40, label: "40" },
  { value: 60, label: "60" },
  { value: 100, label: "100" },
];

export default function Refinement() {
  const { items, refine } = useRefinementList({ attribute: "source" });
  const { currentRefinement, refine: refineSortBy } = useSortBy({
    items: sortItems,
  });
  const hitsPerPage = useHitsPerPage({
    items: hitsPerPageItems,
  });

  const currentVal = items
    .filter((item) => item.isRefined)
    .map((item) => item.value);

  useEffect(() => {
    refineSortBy(sortItems[0].value);
  }, [refineSortBy]);

  function SelectItem(props: ComboboxLikeRenderOptionInput<ComboboxItem>) {
    return (
      <Group justify="space-between" w="100%">
        <Box
          style={{
            gap: "0.5em",
            display: "flex",
            justifyContent: "flex-start",
            alignItems: "center",
          }}
        >
          {currentVal.includes(props.option.value) && (
            <CheckIcon
              style={{
                opacity: "0.4",
                width: "0.8em",
                minWidth: "0.8em",
                height: "0.8em",
              }}
            />
          )}
          {props.option.label}
        </Box>
        <Badge>
          {items.find((item) => item.value === props.option.value)?.count}
        </Badge>
      </Group>
    );
  }

  return (
    <Group justify="space-between" align="center" my="md">
      <Group>
        <Select
          data={sortItems}
          value={currentRefinement}
          defaultValue={sortItems[0].value}
          onChange={(value) => value && refineSortBy(value)}
          label="Sort by"
        />
        <MultiSelect
          styles={{
            wrapper: {
              width: rem(300),
            },
          }}
          data={items.map((item) => ({
            value: item.label,
            label: SourceLabelMap[item.label],
          }))}
          renderOption={SelectItem}
          value={currentVal}
          label="Source"
          clearable
          onChange={(values) => {
            const diff = values
              .filter((value) => !currentVal.includes(value))
              .concat(currentVal.filter((value) => !values.includes(value)));
            diff.forEach((value) => refine(value));
          }}
        />
      </Group>
      <Group w={rem(96)}>
        <Select
          data={hitsPerPageItems.map((item) => ({
            value: item.value.toString(),
            label: item.label.toString(),
          }))}
          value={hitsPerPage.items
            .find((item) => item.isRefined)
            ?.value.toString()}
          onChange={(value) => value && hitsPerPage.refine(parseInt(value))}
          label="Hits per page"
        />
      </Group>
    </Group>
  );
}
