import React, {useEffect, useMemo, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {FormProvider} from 'react-hook-form';
import {
  IconBinary,
  IconCash,
  IconNumbers,
  IconPercentage,
} from '@tabler/icons-react-native';
import {
  ScrollViewWithFooter,
  Divider,
  InputClassicController,
  InputDateController,
  InputSelectController,
  InputSelectOption,
} from '@components';
import {useGetSubordinates} from '@hooks/useGetSubordinates';
import {useGetGoalCycles, useCreateGoalForm} from '@modules/goals/hooks';
import {
  GoalValueType,
  GoalType,
  Goal,
  FormGoalsValues,
  GoalCycleStatus,
} from '@modules/goals/interfaces';
import {GOAL_TITLE_MAX_LENGTH} from '@modules/goals/constants';
import {GoalFormSK} from '@modules/goals/skeletons/GoalFormSK';
import {useUser} from '@redux/selectors';
import {useTheme} from '@shared/theme';
import {getCompleteName} from '@shared/utils/generics';
import {useCommunityFeature} from '@stores/communityFeatures';

import {PriorityPills} from '../PriorityPills';
import {TextWithTooltip} from '../TextWithTooltip';
import {styles} from './styles';
import {OwnerSelector} from './components/OwnerSelector';
import {InputGoalDescription} from './components/InputGoalDescription';
import {GoalValueSection} from './components/GoalValueSection';
import {Note} from './components/Note';
import {NoSaveModal} from './components/NoSaveModal';

interface Props {
  isLoading: boolean;
  onSave: (formValues: FormGoalsValues) => void;
  initialValues?: Partial<Goal>;
  isNoSaveModalVisible?: boolean;
  setIsNoSaveModalVisible?: (isVisible: boolean) => void;
}

export function GoalForm({
  isLoading,
  onSave,
  initialValues,
  isNoSaveModalVisible,
  setIsNoSaveModalVisible,
}: Props) {
  const {t} = useTranslation();
  const {theme} = useTheme();
  const hideBinaryValue = useCommunityFeature('GOALS_HIDE_BINARY_VALUE_TYPE');
  const hidePrioritySelector = useCommunityFeature(
    'GOALS_HIDE_PRIORITY_SELECTOR',
  );
  const [rangeDates, setRangeDates] = useState<{min?: Date; max?: Date}>({});

  const user = useUser();
  const methods = useCreateGoalForm({initialValues});
  const {setValue} = methods;

  const startDate = methods.watch('startDate');
  const ownerIds = methods.watch('ownerIds');
  const goalCycleId = methods.watch('goalCycleId');

  const {subordinates, isLoadingSubordinates, isFetchingSubordinates} =
    useGetSubordinates(true);

  const {
    cycles = [],
    isLoadingCycles,
    getNextPage,
    isFetchingNextPage: isFetchingNextPageCycle,
    isFetchingCycles,
  } = useGetGoalCycles({
    statuses: [GoalCycleStatus.DRAFT, GoalCycleStatus.IN_PROGRESS]?.join(','),
  });

  const typeOptions = useMemo(
    () => [
      {id: GoalType.INDIVIDUAL, label: t('goals.individual')},
      {id: GoalType.COMPANY, label: t('goals.new.company')},
    ],
    [t],
  );
  const valueTypeOptions = useMemo(
    () =>
      [
        (!initialValues?.valueType ||
          initialValues?.valueType === GoalValueType.BINARY) &&
          !hideBinaryValue && {
            id: GoalValueType.BINARY,
            label: t('goals.new.binary'),
            AvatarProps: {Icon: IconBinary},
          },
        ...(!initialValues || initialValues?.valueType !== GoalValueType.BINARY
          ? [
              {
                id: GoalValueType.NUMBER,
                label: t('goals.new.number'),
                AvatarProps: {Icon: IconNumbers},
              },
              {
                id: GoalValueType.MONETARY,
                label: t('goals.new.monetary'),
                AvatarProps: {Icon: IconCash},
              },
              {
                id: GoalValueType.PERCENTAGE,
                label: t('goals.new.percentage'),
                AvatarProps: {Icon: IconPercentage},
              },
            ]
          : []),
      ].filter(Boolean) as InputSelectOption<GoalValueType>[],
    [initialValues, hideBinaryValue, t],
  );
  const hasFormulas = useMemo(
    () => cycles.find(cycle => cycle.id === goalCycleId)?.hasFormulas || false,
    [cycles, goalCycleId],
  );

  const onChangeCycle = (value: number | string) => {
    const selectedCycle = cycles?.find(c => c.id === value);

    if (selectedCycle?.startDate && selectedCycle?.endDate) {
      setRangeDates({
        min: selectedCycle.startDate,
        max: selectedCycle.endDate,
      });

      if (!selectedCycle?.hasFormulas) {
        methods.setValue('formulaChainId', null);
        methods.setValue('hasMinValue', false);
        methods.setValue('hasMaxValue', false);
      }
      methods.setValue('startDate', new Date(selectedCycle?.startDate));
      methods.setValue('endDate', new Date(selectedCycle?.endDate));
      methods.setValue('minDate', new Date(selectedCycle?.startDate));
      methods.setValue('maxDate', new Date(selectedCycle?.endDate));
      methods.setValue('hasFormula', selectedCycle?.hasFormulas);
    }
  };

  useEffect(() => {
    if (!initialValues?.goalCycleId || cycles.length === 0) {
      return;
    }
    const initialCycle = cycles.find(
      cycle => cycle.id === initialValues.goalCycleId,
    );
    if (!initialCycle) {
      return;
    }
    setValue('hasFormula', initialCycle.hasFormulas);
    setValue('startDate', new Date(initialCycle.startDate ?? Date.now()));
    setValue('endDate', new Date(initialCycle.endDate ?? Date.now()));
    setValue('minDate', new Date(initialCycle.startDate ?? Date.now()));
    setValue('maxDate', new Date(initialCycle.endDate ?? Date.now()));
    setRangeDates({
      min: initialCycle.startDate,
      max: initialCycle.endDate,
    });
  }, [cycles, initialValues?.goalCycleId, setValue]);

  const cycleOptions = useMemo(
    () => cycles.map(cycle => ({id: cycle.id, label: cycle.name})),
    [cycles],
  );

  const isLoadingData = useMemo(
    () =>
      isLoadingCycles ||
      isLoadingSubordinates ||
      isFetchingCycles ||
      isFetchingSubordinates,
    [
      isLoadingCycles,
      isLoadingSubordinates,
      isFetchingCycles,
      isFetchingSubordinates,
    ],
  );

  if (isLoadingData) {
    return <GoalFormSK />;
  }

  const onCloseNoSaveModal = () => setIsNoSaveModalVisible?.(false);

  return (
    <>
      <ScrollViewWithFooter
        style={[
          styles.container,
          {backgroundColor: theme.background.layout.default},
        ]}
        contentContainerStyle={styles.content}
        onSubmit={methods.handleSubmit(onSave)}
        submitText={t('general.save')}
        isButtonLoading={isLoading}
        buttonSubmitDisabled={isLoadingData}
        sticky={false}>
        <FormProvider {...methods}>
          <InputClassicController
            name="title"
            label={t('goals.new.title')}
            placeholder={t('goals.new.title')}
            maxLength={GOAL_TITLE_MAX_LENGTH}
            showCounter
          />
          <InputGoalDescription />
          <Divider />
          <InputSelectController
            name="goalCycleId"
            placeholder={t('goals.new.target_cycle')}
            label={t('goals.new.target_cycle')}
            options={cycleOptions}
            onChange={onChangeCycle}
            disabled={isLoadingCycles || isFetchingNextPageCycle || !cycles}
            onEndReached={getNextPage}
            showRadioButtonItem
          />
          <TextWithTooltip
            label={t('goals.new.how_measure_progress')}
            tooltip={t(
              `goals.new.measure_info${initialValues?.id ? '_edit' : ''}`,
            )}
          />
          <GoalValueSection
            valueTypeOptions={valueTypeOptions}
            hasFormula={hasFormulas}
          />
          <Divider />
          <InputDateController
            name="startDate"
            label={t('goals.start_date')}
            minDate={rangeDates.min}
            maxDate={rangeDates.max}
          />
          <InputDateController
            name="endDate"
            label={t('goals.ending_date')}
            minDate={startDate}
            maxDate={rangeDates.max}
          />
          <OwnerSelector
            subordinates={subordinates}
            isLoadingSubordinates={isLoadingSubordinates}
            ownerIds={ownerIds}
          />
          <InputSelectController<GoalType>
            name="type"
            placeholder={t('general.type')}
            label={t('general.type')}
            options={typeOptions}
            disabled
            helper={t('goals.new.type_individual_description')}
          />
          {!hidePrioritySelector && <PriorityPills name="priority" />}
          <Note />
        </FormProvider>
      </ScrollViewWithFooter>
      <NoSaveModal
        isVisible={!!isNoSaveModalVisible}
        onClose={onCloseNoSaveModal}
        isSelfGoal={ownerIds.length === 1 && ownerIds[0] === user.id}
        userName={
          ownerIds.length === 1
            ? getCompleteName(
                subordinates.find(
                  subordinate => subordinate.id === ownerIds[0],
                ) || user,
              )
            : undefined
        }
      />
    </>
  );
}
