import { useDispatch, useSelector } from 'react-redux';

import {
  CONDITION_ENUM_AND,
  CONDITION_ENUM_OR,
  RULE_TYPE_ALL_MY_VIDEO,
  SAVE_RULE_ACTION_REMOVE,
  SAVE_RULE_ACTION_SAVE,
  SHARE_WITH_TYPE_ALL_RELATED_USERS,
} from '../constants';

import { createEmptyRules, mapArray } from '@/modules/userRulesSettings/helpers';
import { rulesSelector } from '@/modules/userRulesSettings/redux/selectors';
import { saveRulesAction, setModuleStateAction } from '@/modules/userRulesSettings/redux/slices';

const useLogic = ({ setRuleToDelete }) => {
  const dispatch = useDispatch();
  const rules$ = useSelector(rulesSelector);

  // Add empty rule
  const handleRuleAddNew = () => {
    const rules = [].concat(
      createEmptyRules({
        uiIndex: `${Math.random()}-${Math.random()}`,
        indexInArray: rules$.length + 1,
      }),
      rules$,
    );

    dispatch(setModuleStateAction({ rules, search: '' }));
  };

  // Rules container handlers
  const handleRuleTitleChange = (newTitle, ruleIndex) => {
    const rules = mapArray(rules$, {
      ruleName: (rule) => (rule.uiIndex === ruleIndex ? newTitle : rule.ruleName),
      uiIsNameInEditMode: (rule) => (rule.uiIndex === ruleIndex ? !rule.uiIsNameInEditMode : rule.uiIsNameInEditMode),
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleRuleToggleTitleEditMode = (ruleIndex) => {
    const rules = mapArray(rules$, {
      uiIsNameInEditMode: (rule) => (rule.uiIndex === ruleIndex ? !rule.uiIsNameInEditMode : rule.uiIsNameInEditMode),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleRuleToggleOpen = (ruleIndex) => {
    const rules = mapArray(rules$, {
      uiIsOpen: (rule) => (rule.uiIndex === ruleIndex ? !rule.uiIsOpen : rule.uiIsOpen),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleRulesDeleteShowConfirm = (rule) => setRuleToDelete(rule);
  const handleRuleDelete = (ruleIndex) => {
    const rules = rules$.filter((rule) => rule.uiIndex !== ruleIndex);

    dispatch(setModuleStateAction({ rules }));
    setRuleToDelete(null);
    dispatch(saveRulesAction(SAVE_RULE_ACTION_REMOVE));
  };

  // rule select handlers
  const handleRuleSelectChangeType = (type, ruleIndex, ruleSelectTypeIndex) => {
    const rules = mapArray(rules$, {
      ruleSelectType: (rule) => {
        if (rule.uiIndex === ruleIndex) {
          return type === RULE_TYPE_ALL_MY_VIDEO
            ? [{ type }]
            : rule.ruleSelectType.map((o, index) => ({
                ...o,
                type: index === ruleSelectTypeIndex ? type : o.type,
                value: index === ruleSelectTypeIndex ? [] : o.value,
              }));
        }
        return rule.ruleSelectType;
      },
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleRuleSelectDelete = (ruleIndex, ruleSelectTypeIndex) => {
    const rules = mapArray(rules$, {
      ruleSelectType: (rule) => {
        const filtered =
          rule.uiIndex === ruleIndex
            ? rule.ruleSelectType.filter((o, index) => index !== ruleSelectTypeIndex)
            : rule.ruleSelectType;

        return filtered.map((r, rIndex) => ({
          ...r,
          condition: rIndex === 0 ? CONDITION_ENUM_AND : r.condition,
        }));
      },
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleRuleSelectAdd = (ruleIndex) => {
    const rules = mapArray(rules$, {
      ruleSelectType: (rule) =>
        rule.uiIndex === ruleIndex
          ? [].concat(rule.ruleSelectType, { type: '', condition: CONDITION_ENUM_OR })
          : rule.ruleSelectType,
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleAutocompleteRuleSelectOnChange = (value, ruleIndex, ruleSelectTypeIndex) => {
    const valueNormalize = value.map((o) => (typeof o === 'string' ? o.trim() : o));

    const rules = mapArray(rules$, {
      ruleSelectType: (rule) =>
        rule.uiIndex === ruleIndex
          ? rule.ruleSelectType.map((o, index) => ({
              ...o,
              value: index === ruleSelectTypeIndex ? valueNormalize : o.value,
            }))
          : rule.ruleSelectType,
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleRuleSelectChangeCondition = (condition, ruleIndex, ruleSelectTypeIndex) => {
    const rules = mapArray(rules$, {
      ruleSelectType: (rule) => {
        if (rule.uiIndex === ruleIndex) {
          return rule.ruleSelectType.map((o, index) => ({
            ...o,
            condition: index === ruleSelectTypeIndex ? condition : o.condition,
          }));
        }
        return rule.ruleSelectType;
      },
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  // share with handlers
  const handleShareWithChangeType = (type, ruleIndex, ruleSelectTypeIndex) => {
    const rules = mapArray(rules$, {
      ruleShareWithType: (rule) => {
        if (rule.uiIndex === ruleIndex) {
          return type === SHARE_WITH_TYPE_ALL_RELATED_USERS
            ? [{ type }]
            : rule.ruleShareWithType.map((o, index) => ({
                ...o,
                type: index === ruleSelectTypeIndex ? type : o.type,
                value: index === ruleSelectTypeIndex ? [] : o.value,
              }));
        }
        return rule.ruleShareWithType;
      },
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleShareWithDelete = (ruleIndex, ruleSelectTypeIndex) => {
    const rules = mapArray(rules$, {
      ruleShareWithType: (rule) =>
        rule.uiIndex === ruleIndex
          ? rule.ruleShareWithType.filter((o, index) => index !== ruleSelectTypeIndex)
          : rule.ruleShareWithType,
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleShareWithAdd = (ruleIndex) => {
    const rules = mapArray(rules$, {
      ruleShareWithType: (rule) =>
        rule.uiIndex === ruleIndex ? [].concat(rule.ruleShareWithType, { type: '' }) : rule.ruleShareWithType,
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  const handleAutocompleteShareWithOnChange = (value, ruleIndex, ruleSelectTypeIndex) => {
    const rules = mapArray(rules$, {
      ruleShareWithType: (rule) =>
        rule.uiIndex === ruleIndex
          ? rule.ruleShareWithType.map((o, index) => ({ ...o, value: index === ruleSelectTypeIndex ? value : o.value }))
          : rule.ruleShareWithType,
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? false : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  // save/cancel handlers
  const handleRuleSave = (ruleIndex) => {
    const rules = mapArray(rules$, {
      initialFromApi: (rule) =>
        rule.uiIndex === ruleIndex && !rule.uiIsSaved
          ? {
              ruleSelectType: rule.ruleSelectType,
              ruleShareWithType: rule.ruleShareWithType,
              ruleName: rule.ruleName,
            }
          : rule.initialFromApi,
      uiIsSaved: (rule) => (rule.uiIndex === ruleIndex ? true : rule.uiIsSaved),
    });

    dispatch(setModuleStateAction({ rules }));
    dispatch(saveRulesAction(SAVE_RULE_ACTION_SAVE));
  };

  const handleRuleCancel = (ruleIndex) => {
    const rules = mapArray(rules$, {
      ruleSelectType: (rule) => (rule.uiIndex === ruleIndex ? rule.initialFromApi.ruleSelectType : rule.ruleSelectType),
      ruleShareWithType: (rule) =>
        rule.uiIndex === ruleIndex ? rule.initialFromApi.ruleShareWithType : rule.ruleShareWithType,
      ruleName: (rule) => (rule.uiIndex === ruleIndex ? rule.initialFromApi.ruleName : rule.ruleName),
    });

    dispatch(setModuleStateAction({ rules }));
  };

  return {
    handleRuleAddNew,
    handleRuleTitleChange,
    handleRuleToggleTitleEditMode,
    handleRuleToggleOpen,
    handleRulesDeleteShowConfirm,
    handleRuleDelete,

    handleRuleSelectChangeType,
    handleRuleSelectDelete,
    handleRuleSelectAdd,
    handleAutocompleteRuleSelectOnChange,
    handleRuleSelectChangeCondition,

    handleShareWithChangeType,
    handleShareWithDelete,
    handleShareWithAdd,
    handleAutocompleteShareWithOnChange,

    handleRuleSave,
    handleRuleCancel,
  };
};

export default useLogic;
