import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { Autocomplete, Box, Checkbox, Popper, styled, TextField, Tooltip, Typography } from "@mui/material";
import { DataContext } from "../../context/Context";
import ComponentWrapper from "../../common/ComponentWrapper";
import { getFieldName } from "../../permissions/getFieldName";
import { inputProps } from "../../interface/inputfieldProps";
import { getComponentProps, getSchemaProps } from "../../common/getComponentProps";
import _ from "lodash";
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
import CheckBoxIcon from "@mui/icons-material/CheckBox";
import MultiSelectSearchPanel from "./MultiSelectSearchPanel";
import { useJsonForms } from "@jsonforms/react";

const StyledAutocompletePopper = styled("div")(({ theme, style }: { theme: any, style: any }) => ({
  ...theme.AutoCompleteStyle,
  ...style
}));

const CustomPopper = (props: any) => {
  const { theme, style, anchorEl, ...other } = props; 
  return (
    <Popper
      {...other}
      anchorEl={anchorEl}
      disablePortal
      style={{ width: anchorEl?.clientWidth }}   
    >
      <StyledAutocompletePopper theme={theme} style={style} {...other} />
    </Popper>
  );
};

export const ImpaktAppsAutoComplete = memo(function CustomAutoComplete(
  props: inputProps | any
) {
  const {
    errors,
    uischema,
    rootSchema,
    data,
    required,
    handleChange,
    path,
    schema,
    options,
  } = props.props;
  const uischemaData = uischema?.config?.main;
  const { pageName, permissions, theme, setSchema, serviceProvider } =
    useContext(DataContext);

  const ctx = useJsonForms();
  const dynamicStyle = useMemo(() => {
  return serviceProvider(
   ctx,
   {
    onClick: uischema.config?.main?.styleFunction || 'getStyle',
   },
   {
    event: { _reactName: 'onClick' },
    path,
   },
  );
 }, [data, path]);

  const componentStyle = useMemo(
    () => ({ ...uischema.config?.style, ...dynamicStyle }),
    [uischema.config?.style, dynamicStyle]
  );

  const fieldName = getFieldName(path);
  const [changeState, setChangeState] = useState("");
  const [selectOptions, setSelectOptions] = useState(
    options || uischemaData.options || []
  );
  const [value, setValue] = useState<any>(uischemaData.multiple ? [] : "");

  const [open, setOpen] = useState(false);
  const [dropdownSearch, setDropdownSearch] = useState("");
  const isDisabled = getSchemaProps(schema, rootSchema).disabled;

  const inputRef = useRef<HTMLInputElement>(null);

  const handleRemoveChip = useCallback(
    (val: any) => {
      setValue((prev: any[]) => {
        const next = prev.filter((option) => option.value !== val);
        handleChange(path, next.length === 0 ? undefined : next.map((e) => e?.value));
        return next;
      });

      setTimeout(() => inputRef.current?.focus(), 0);
    },
    [handleChange, path]
  );

  const PopperSlot = useMemo(
    () => (props: any) => (
      <CustomPopper
        {...props}
        theme={theme}
        style={componentStyle?.AutoCompleteStyle}
      />
    ),
    [componentStyle?.AutoCompleteStyle]
  );

  const triggerDisplayValue = useMemo(() => {
    if (!uischemaData.multiple) return undefined;
    if (!Array.isArray(value) || value.length === 0) return "";
    if (value.length === 1) return value[0]?.label ?? "";
    return `${value.length} selected`;
  }, [uischemaData.multiple, value]);

  const MultiSelectDropdownPanelProps = useMemo(
    () => ({
      selectedOptions: Array.isArray(value) ? value : [],
      searchValue: dropdownSearch,
      onSearchChange: setDropdownSearch,
      searchPlaceholder: uischemaData?.searchPlaceholder,
      onRemoveChip: handleRemoveChip,
      styleConfig: componentStyle,
      isDisabled,
      appTheme: theme
    }),
    [value, dropdownSearch, uischemaData?.searchPlaceholder, handleRemoveChip, componentStyle, isDisabled, theme]
  );

  const filteredSelectOptions = useMemo(() => {
    if (uischemaData.lazyLoading) return selectOptions;
    if (!uischemaData.multiple || !dropdownSearch) return selectOptions;
    return selectOptions.filter((opt: any) =>
      opt.label?.toLowerCase().includes(dropdownSearch.toLowerCase())
    );
  }, [selectOptions, dropdownSearch, uischemaData.multiple]);

  useEffect(() => {
    setSelectOptions(options || []);
  }, [options]);

  useEffect(() => {
    updateFreeSoloOptions();
  }, []);
  function updateFreeSoloOptions() {
    if (uischemaData.freeSolo && !uischemaData.lazyLoading && data) {
      // let Updatedresponse = [{const:data||"",title:data||""}];
      if (options) {
        const OptionsClone = _.cloneDeep(options);
        const updatedOptions = OptionsClone?.map((e: any) => {
          return { const: e.value, title: e.label };
        });
        const filterResult = updatedOptions.filter((e) => {
          return e.const === data;
        });
        if (filterResult.length > 0) {
          return;
        }
        updatedOptions.push({ const: data || "", title: data || "" });
        updateSchema({
          options,
          response: updatedOptions,
          setSchema,
          path,
          uischemaData,
        });
      } else {
        updateSchema({
          options,
          response: [{ const: data || "", title: data || "" }],
          setSchema,
          path,
          uischemaData,
        });
      }
    }
  }
  const debouncedFunction = useMemo(
  () =>
    _.debounce((value: string, currentData: any) => {
      serviceProvider(
        props.ctx,
        {
          ...uischemaData,
          onInputChange: uischemaData.lazyLoadFunction || "getSelectOptions",
        },
        {
          event: { _reactName: "onInputChange" },
          path,
          ...uischemaData.additionalData,
          paramValue: {
            path,
            serachValue: value,
            currentValue: currentData,
          },
        }
      ).then((response: any) => {
        if (response) {
          if (uischemaData.freeSolo) {
            response[response.length] = { const: changeState, title: changeState };
          }
          updateSchema({ options, response, setSchema, path, uischemaData });
          const filteredOptions = [];
          response.forEach((e) => {
            if (!data?.includes(e?.const)) {
              filteredOptions.push({ label: e.title, value: e.const });
            }
          });
          setSelectOptions(filteredOptions);
        }
      });
    }, 1000),
  [changeState, uischemaData, serviceProvider, path, options, setSchema, props.ctx, data]  
);

  useEffect(() => {
    if (!uischemaData.lazyLoading) return;
    debouncedFunction(dropdownSearch, data);
  }, [dropdownSearch]);

  const findOptions = () => {
    const value = data
      ? uischemaData.multiple
        ? options?.filter((o) => data.includes(o.value)) ?? []
        : options?.find((o) => o.value === data) ?? data
      : uischemaData.multiple
      ? []
      : "";
    setValue(value);
  };
  useEffect(() => {
    if (options) {
      findOptions();
    }
  }, [options, data]);

  const computedProps = getComponentProps(
    `${pageName}:${fieldName}`,
    permissions,
    schema,
    rootSchema
  );
  return (
    <ComponentWrapper
        {...computedProps}
    >
      <Box
        onBlur={(e: React.FocusEvent) => {
          if (!uischemaData.multiple) return;
          if (!e.currentTarget.contains(e.relatedTarget as Node)) {
            setOpen(false);
            setDropdownSearch("");
          }
        }}
      >
      <Tooltip
        title={uischemaData?.toolTip || ''}
        placement={uischemaData?.toolTipPosition || "top"}
        arrow
      >
      <Autocomplete
        limitTags={uischemaData?.limitTags || 1}
        open={uischemaData.multiple ? open : undefined}
        onOpen={uischemaData.multiple ? () => setOpen(true) : undefined}
        onClose={uischemaData.multiple ? () => {} : undefined}
        openOnFocus={uischemaData.multiple ? false : undefined}
        clearOnBlur={uischemaData.multiple ? false : undefined}
        disabled={isDisabled && !uischemaData.multiple}
        onChange={(event, newValue: any) => {
          if (uischemaData.multiple) {
            if(isDisabled) return; 
            if (newValue.length === 0) {
              handleChange(path, undefined);
            } else {
              handleChange(
                path,
                newValue.map((e) => e?.value || e)
              );
            }
          } else {
            handleChange(path, newValue === null ? undefined : newValue.value);
          }
        }}
        filterOptions={uischemaData.lazyLoading ? (option) => option : undefined}
        onInputChange={(event, newInputValue) => {
          if (uischemaData.multiple) return;
          if (uischemaData.lazyLoading) setDropdownSearch(newInputValue);
        }}
        onMouseLeave={() => updateFreeSoloOptions()}
        // placeholder={uischemaData.placeholder}
        sx={{
          ...theme.InputFieldStyle,
          ...(computedProps.disabled && {
            '& .MuiOutlinedInput-root.Mui-disabled': {
              borderRadius: '12px'
            },
            '& .MuiOutlinedInput-input.Mui-disabled': {
              WebkitTextFillColor:theme.myTheme.palette?.disabled?.text
            },
          }),
            ...(isDisabled && uischemaData.multiple && {
              "& .MuiOutlinedInput-root": {
                  "& .MuiOutlinedInput-notchedOutline": {
                    borderColor: theme.myTheme.palette.primary?.main,
                  },
                  "& input": {
                    WebkitTextFillColor: theme.myTheme.palette?.disabled?.text,
                  },
                },
                "& .MuiInputLabel-root": {
                  color: theme.myTheme.palette?.disabled?.text,
                },
                "& .MuiInputLabel-root.Mui-focused": {
                  color:
                    theme.myTheme.palette?.disabled?.text,
                },
                "& .MuiSvgIcon-root": {
                  color: theme.myTheme.palette?.disabled?.text,
                },
            }),
          ...componentStyle
        }}
        freeSolo={uischemaData.freeSolo ? true : false}
        multiple={uischemaData.multiple ? true : false}
        id={path}
        options={filteredSelectOptions ?? []}
        value={value}
        slots={{
          popper: PopperSlot,
          ...(uischemaData.multiple ? { paper: MultiSelectSearchPanel } : {}),
        }}
        slotProps={{
          listbox: {
            sx: {
              overflowY: "auto",
              "&::-webkit-scrollbar": { width: "4px" },
              "&::-webkit-scrollbar-thumb": {
                backgroundColor: theme.myTheme.palette?.secondary?.light,
                borderRadius: "4px",
              },
            },
          },
          ...(uischemaData.multiple ? { paper: MultiSelectDropdownPanelProps } : {}),
          ...(uischemaData.multiple
            ? {
                popupIndicator: {
                  onClick: (e: any) => {
                    e.preventDefault();
                    e.stopPropagation();
                    setOpen((prev) => !prev);
                  },
                },
              }
            : {}),
        }}
        renderTags={uischemaData.multiple ? () => null : undefined}
        renderOption={
          uischemaData.multiple
            ? (optionProps: any, option: any, { selected: isSelected }: any) => (
                <li
                  {...optionProps}
                  key={option.value}
                  style={{
                    display: "flex",
                    alignItems: "center",
                    gap: "8px",
                    padding: "8px 12px",
                    backgroundColor: isSelected ? "#cae4e6" : "transparent",
                    cursor: isDisabled ? "default" : "pointer",
                  }}
                >
                  <Checkbox
                    size="small"
                    checked={isSelected}
                    icon={<CheckBoxOutlineBlankIcon sx={{ fontSize: 20, color: theme.myTheme.palette?.secondary?.light }} />}
                    checkedIcon={<CheckBoxIcon sx={{ fontSize: 20, color: theme.myTheme.palette?.primary.main }} />}
                    sx={{ padding: 0 }}
                    disableRipple
                    onMouseDown={(e) => e.preventDefault()}
                  />
                  <Typography
                    sx={{
                      fontSize: componentStyle?.optionFontSize || "14px",
                      color: isSelected
                        ? theme.myTheme.palette?.primary.main
                        : `${theme.myTheme.palette?.text?.primary}110`,
                      fontWeight: isSelected ? 500 : 400,
                    }}
                  >
                    {option.label}
                  </Typography>
                </li>
              )
            : undefined
        }
        renderInput={(params) => (
            <TextField
              {...params}
              inputRef={inputRef}
              size={uischemaData?.size ?? "medium"}
              helperText={
                errors !== ""
                  ? errors.includes("pattern")
                    ? uischemaData?.errorMessage
                    : errors || "\u00A0"
                  : uischemaData?.helperText || "\u00A0"
              }
              error={errors !== "" ? true : false}
              sx={{
                ...theme.InputFieldStyle,
                ...uischema?.config?.TextFieldStyle,
                "& input": {
                  fontSize: theme.myTheme.typography.fontSize
                },
                // maxHeight: "34px"
              }}
              slotProps={{
                inputLabel: {
                  sx: { ...componentStyle?.inputLabelStyle },
                },
                ...(uischemaData.multiple
                  ? {
                      htmlInput: {
                        ...params.inputProps,
                        value: triggerDisplayValue,
                        readOnly: true,
                        style: { cursor: "pointer", caretColor: "transparent" },
                      },
                    }
                  : {}),
              }}
              variant={uischemaData?.variant || "outlined"}
              label={uischemaData?.label}
              required={required}
              placeholder={uischemaData?.placeholder}
              onChange={
                uischemaData.freeSolo
                  ? (newValue) => {
                      setChangeState(newValue.target.value);
                      handleChange(path, newValue.target.value);
                    }
                  : () => {}
              }
            />
        )}
      />
      </Tooltip>
      </Box>
    </ComponentWrapper>
  );
});

export default ImpaktAppsAutoComplete;

function updateSchema(param) {
  if (param.uischemaData.multiple) {
    param.setSchema((pre: any) => {
      return {
        ...pre,
        properties: {
          ...pre.properties,
          [param.path]: {
            ...pre.properties?.[param.path],
            type: "array",
            items: {
              oneOf: param.response,
            },
          },
        },
      };
    });
  } else {
    param.setSchema((pre: any) => {
      return {
        ...pre,
        properties: {
          ...pre.properties,
          [param.path]: {
            ...pre.properties?.[param.path],

            uniqueItems: true,
            oneOf: param.response || [],
          },
        },
      };
    });
  }
}