import "./style.pcss";

import type { FC, ReactElement } from "react";
import {
  createRef, useEffect, useImperativeHandle, useRef, useState,
} from "react";
import type {
  ICheckerGroup,
  ICheckerGroupItemsGroup,
  ICheckerGroupRef,
  TCheckerGroupGetItem,
  TCheckerGroupGetItemArg,
  TCheckerGroupItem,
  TCheckerGroupItemsProp,
  TCheckerGroupOnChangeFn,
} from "./config/types";
import { getCheckedItems } from "./utils/getCheckedItems";
import type { IComponentBaseProps } from "../../types/components/index";
import { useCN } from "../../utils/react/useCN";
import { Checker } from "../checker";
import type { IInputEventParams } from "../input/config/types";

/**
 * Группа чекеров
 * @returns {ReactElement}
 */
const CheckerGroup: FC<IComponentBaseProps & ICheckerGroup> = ({
  baseClass = "checkerGroup",
  extraAttrs = {},
  extraClasses = {},
  children = null,
  items = [],
  form,
  type = "checkbox",
  onChange = null,
  getItem = null,
  emptyPlaceholder = "Нет элементов",
  ref,
}): ReactElement => {

  const { getCN } = useCN(baseClass);

  const [ list, setList ] = useState<TCheckerGroupItemsProp>(items);

  const listRef = useRef<HTMLUListElement | null>(null);
  const containerRef = useRef<HTMLFieldSetElement | null>(null);

  const setScroll = (value = 0) => {
    if (listRef.current) {
      listRef.current.scrollTop = value;
    }
  };

  useEffect(() => {
    setList(items);
  }, [ items ]);

  useEffect(() => {
    setScroll();
  }, []);

  const onInputChange = (e: IInputEventParams) => {
    if (typeof onChange === "function") {
      onChange(e, setList);
    } else {
      const { name, value, checked } = e.event.target as HTMLInputElement;
      setList((checkers) => {
        return getCheckedItems(checkers, {
          type, name, value, checked,
        });
      });
    }
  };

  const getList = (items: TCheckerGroupItemsProp = [], nestedKey = 0) => {
    if (!items.length) {
      return <li className={getCN("item", { isEmpty: true })}>{emptyPlaceholder}</li>;
    }

    return items.map((item, index) => {
      const checker = <Checker type={type} onChange={onInputChange} form={form} {...item} />;
      const comp = typeof getItem === "function" ? getItem({
        item, index, checker, getCN,
      }) : checker;

      const isInnerList = "items" in item && Array.isArray(item.items);

      const key = `${index}${nestedKey}${"name" in item ? item.name : ""}${"value" in item ? item.value : ""}${"isChecked" in item ? item.isChecked : false}`;

      return (
        <li key={key} className={getCN("item")}>
          {!!item.label && isInnerList && <p className={getCN("label")}>{item.label}</p>}
          {isInnerList ? <ul className={getCN("list", { isInner: true })}>
            {getList(item.items, index)}
          </ul> : comp}
        </li>
      );
    });
  };

  useImperativeHandle(ref, (): ICheckerGroupRef => ({
    el: containerRef.current,
    ref: createRef(),
    stateActions: null,
    getData: () => null,
    utils: {
      setScroll,
    },
  }), []);

  return (
    <fieldset ref={containerRef} className={getCN("", extraClasses)} {...extraAttrs}>
      {children || (
        <ul className={getCN("list")} ref={listRef}>
          {getList(list)}
        </ul>
      )}
    </fieldset>
  );

};

export type {
  ICheckerGroup,
  ICheckerGroupItemsGroup,
  ICheckerGroupRef,
  TCheckerGroupGetItem,
  TCheckerGroupGetItemArg,
  TCheckerGroupItem,
  TCheckerGroupItemsProp,
  TCheckerGroupOnChangeFn,
};

export {
  CheckerGroup,
};
