import { Autocomplete } from "@mui/material";
import { createFilterOptions } from "@mui/material/Autocomplete";
import TagChip from "components/ui/TagChip";
import ConductorInput from "components/ui/inputs/ConductorInput";
import XCloseIcon from "components/icons/XCloseIcon";
import { ReactNode } from "react";
import { autocompleteStyle } from "shared/styles";
import { TagDto } from "types/Tag";

type ReplaceTagsInputProps = {
  onChange?: (tags: string[]) => void | null;
  onInputChange?: (value: string) => void;
  label?: ReactNode;
  tags: TagDto[];
  options: TagDto[];
};
type SuggestValueType = { title: string; inputValue: string };

import { isValidTag } from "components/features/tags/tagUtils";

const filter = createFilterOptions<SuggestValueType>();

const ReplaceTagsInput = ({
  label = "Tags",
  onChange = () => null,
  onInputChange,
  tags = [],
  options = [],
}: ReplaceTagsInputProps) => {
  return (
    <Autocomplete
      id="tag-autocomplete-input"
      multiple
      freeSolo
      options={options.map((tag: TagDto) => {
        return (
          tag && {
            inputValue: `${tag.key}:${tag.value}`,
            title: `${tag.key}:${tag.value}`,
          }
        );
      })}
      defaultValue={tags.map((tag: TagDto) => {
        return (
          tag && {
            inputValue: `${tag.key}:${tag.value}`,
            title: `${tag.key}:${tag.value}`,
          }
        );
      })}
      renderTags={(value, getTagProps) =>
        value.map((option, index) => {
          const label = (
            option?.inputValue ? option.inputValue : option
          ) as string;
          const { key, ...otherTagProps } = getTagProps({ index });
          const invalid = !isValidTag(label);
          return (
            <TagChip
              key={key}
              id={`${label}-tag-chip`}
              label={label}
              color={invalid ? "error" : undefined}
              {...otherTagProps}
              sx={{
                "& .MuiSvgIcon-root": {
                  background: "transparent",
                },
              }}
            />
          );
        })
      }
      getOptionLabel={(option) => {
        // Value selected with enter, right from the input
        if (typeof option === "string") {
          return option;
        }
        // Add "xxx" option created dynamically
        if (option.inputValue) {
          // Regular option
          return option.title;
        }
        // Regular option
        return option.title;
      }}
      filterOptions={(options, params) => {
        const filtered = filter(options, params);

        const { inputValue } = params;
        // Suggest the creation of a new value
        const isExisting = options.some(
          (option) => inputValue === option.title,
        );

        if (inputValue !== "" && !isExisting) {
          filtered.push({
            inputValue,
            title: `Add "${inputValue}"`,
          });
        }

        return filtered;
      }}
      onInputChange={(_event, value) => {
        onInputChange?.(value);
      }}
      onChange={(_event, newValue: (string | SuggestValueType)[]) => {
        onChange(
          newValue.map((val: string | SuggestValueType) =>
            typeof val === "string" ? val : val.inputValue,
          ),
        );
      }}
      renderInput={(params) => (
        <ConductorInput
          {...params}
          id="tag-input-field"
          label={label}
          placeholder="e.g.: team:design, region:us-east"
          helperText={
            <span>
              Type a tag name using the <strong>key:value</strong> format and
              press enter to create new tags.
            </span>
          }
        />
      )}
      sx={[autocompleteStyle({ value: tags })]}
      clearIcon={<XCloseIcon />}
    />
  );
};

export default ReplaceTagsInput;
