/* eslint-disable @typescript-eslint/no-explicit-any */

import _ from "lodash";
import { ChooserColumn } from "../../../data/setting";
import ColumnChooserView from "./ColumnChooserView";
import { useEffect, useMemo, useRef, useState } from "react";

export type ColumnChooserProps = {
  uiElementGroupData: Record<string, any>;
  toggleColumnChooser: boolean;
  columns: ChooserColumn[];
  config: { uiElementGroupId: string };
  onChooserClick: () => void;
  onModelUpdate: (
    callBack: ((args: any) => void) | null,
    fieldName: string,
    value: any,
  ) => void;
  setToggleColumnChooser: (status: boolean) => void;
  setTogglePopup: (status: boolean) => void;
};

const ColumnChooser = (props: ColumnChooserProps) => {
  const [searchInput, setSearchInput] = useState("");
  const [localAllColumns, setLocalAllColumns] = useState<ChooserColumn[]>([]);
  const [localSelectedColumns, setLocalSelectedColumns] = useState<
    ChooserColumn[]
  >([]);

  const popupChooserRef = useRef<HTMLDivElement>(null);

  // Reset local state from model when popup opens
  useEffect(() => {
    if (props.toggleColumnChooser) {
      setLocalAllColumns(
        _.cloneDeep(
          props.uiElementGroupData?.setting?.columnChooser?.allColumns ?? [],
        ),
      );
      setLocalSelectedColumns(
        _.cloneDeep(
          props.uiElementGroupData?.setting?.columnChooser?.selectedColumns ??
            [],
        ),
      );
      setSearchInput("");
    }
  }, [props.toggleColumnChooser]);

  const searchedColumns = useMemo(
    () =>
      localAllColumns.filter((c: ChooserColumn) =>
        c.label.toLowerCase().includes(searchInput?.toLowerCase()),
      ),
    [searchInput, localAllColumns],
  );

  const sortedSelectedColumns = useMemo(() => {
    const sColumns = _.cloneDeep(localSelectedColumns);
    return sColumns?.sort((a: ChooserColumn, b: ChooserColumn) => {
      return (a.order ?? 0) - (b.order ?? 0);
    });
  }, [localSelectedColumns]);

  useEffect(() => {
    if (props.toggleColumnChooser) {
      document.addEventListener("mousedown", handleClickOutside);
    } else {
      document.removeEventListener("mousedown", handleClickOutside);
    }
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [props.toggleColumnChooser]);

  const handleClickOutside = (event: MouseEvent) => {
    if (
      popupChooserRef.current &&
      !popupChooserRef.current.contains(event.target as Node) &&
      (event.target as Node).textContent !== "Column Chooser"
    ) {
      props.onChooserClick();
    }
  };

  const onFieldAddOrRemove = (id: number) => {
    const allColumns = _.cloneDeep(localAllColumns);
    const sColumns = _.cloneDeep(localSelectedColumns);
    const sColumn = allColumns.find((a: ChooserColumn) => a.id === id);

    let selectedColumns: ChooserColumn[] = [];
    if (sColumn?.selected) {
      selectedColumns = sColumns?.filter((a: ChooserColumn) => a.id !== id);
      selectedColumns = selectedColumns.map((s, index: number) => {
        s.order = index + 1;
        return s;
      });
    } else if (sColumn) {
      selectedColumns = [
        ...sColumns,
        { ...sColumn, selected: true, order: sColumns.length },
      ];
    }

    allColumns.forEach((column: ChooserColumn) => {
      if (column.id === id) {
        column.selected = !column.selected;
      }
    });

    setLocalAllColumns(allColumns);
    setLocalSelectedColumns(selectedColumns);
  };

  const excludeIncludeToCard = (id: number) => {
    const selectedColumns = _.cloneDeep(localSelectedColumns);
    selectedColumns.forEach((column: ChooserColumn) => {
      if (column.id === id) {
        column.includeInCard = !column.includeInCard;
      }
    });
    setLocalSelectedColumns(selectedColumns);
  };

  const toggleFreeze = (id: number) => {
    const selectedColumns = _.cloneDeep(localSelectedColumns);
    const freezeIndex = selectedColumns.findIndex(
      (column: ChooserColumn) => column.id === id,
    );
    selectedColumns.forEach((column: ChooserColumn, index: number) => {
      if (index <= freezeIndex) {
        column.isFreezed = true;
      } else {
        column.isFreezed = column.primary || false;
      }
    });
    setLocalSelectedColumns(selectedColumns);
  };

  const onChooserApply = () => {
    const updatedUiElementGroupData = {
      ...props.uiElementGroupData,
      setting: {
        ...props.uiElementGroupData.setting,
        columnChooser: {
          ...props.uiElementGroupData.setting.columnChooser,
          allColumns: _.cloneDeep(localAllColumns),
          selectedColumns: _.cloneDeep(localSelectedColumns),
          appliedColumns: _.cloneDeep(sortedSelectedColumns),
        },
      },
    };
    props.setToggleColumnChooser(false);
    props.setTogglePopup(false);
    props.onModelUpdate(
      null,
      props.config.uiElementGroupId,
      updatedUiElementGroupData,
    );
  };

  const onChooserRestore = () => {
    const restoredAll = _.cloneDeep(props.columns);
    const restoredSelected = restoredAll.filter((c) => c.selected);
    setLocalAllColumns(restoredAll);
    setLocalSelectedColumns(restoredSelected);
  };

  const onFieldDragEnd = (result: any) => {
    if (!result.destination) return;
    if (result.destination.index === result.source.index) return;

    const clonedSelectedColumns = _.cloneDeep(sortedSelectedColumns);
    const movedItem = clonedSelectedColumns.splice(result.source.index, 1)[0];
    clonedSelectedColumns.splice(result.destination.index, 0, movedItem);
    clonedSelectedColumns.forEach((column: ChooserColumn, index: number) => {
      column.order = index + 1;
    });

    setLocalSelectedColumns(clonedSelectedColumns);
  };

  return (
    <ColumnChooserView
      popupChooserRef={popupChooserRef}
      allColumns={searchedColumns ?? []}
      selectedColumns={sortedSelectedColumns ?? []}
      onFieldAddOrRemove={onFieldAddOrRemove}
      excludeIncludeToCard={excludeIncludeToCard}
      toggleFreeze={toggleFreeze}
      onChooserApply={onChooserApply}
      onChooserRestore={onChooserRestore}
      onChooserClose={props.onChooserClick}
      onFieldDragEnd={onFieldDragEnd}
      searchInput={searchInput}
      setSearchInput={setSearchInput}
    />
  );
};
export default ColumnChooser;
