import { useMemo } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { useQuery } from 'react-query';

import { isNil } from 'lodash-es';
import InfoOutlinedIcon from '@material-hu/icons/material/InfoOutlined';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuFormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import HuTooltip from '@material-hu/components/design-system/Tooltip';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { goalsKeys } from '../../queries';
import { getGoalCycleRangeFields } from '../../services';
import { Boundary, type GoalCycleRangeFields } from '../../types';
import { isGoalCycleInProgressStatus } from '../../utils';
import { useValueInputRules } from '../hooks/useValueInputRules';

import FormulasAutocomplete, {
  type FormulaOption,
} from './FormulasAutocomplete';

const INPUT_FIELDS_CONFIG = [
  {
    labelKey: 'new.initial_measure',
    fieldName: Boundary.STARTING_VALUE,
    required: true,
  },
  { labelKey: 'new.min_value', fieldName: Boundary.MIN_VALUE, required: false },
  {
    labelKey: 'new.target_measure',
    fieldName: Boundary.OBJECTIVE_VALUE,
    required: true,
  },
  { labelKey: 'new.max_value', fieldName: Boundary.MAX_VALUE, required: false },
];

/**
 * Determines which input fields should be displayed based on formula configuration
 */
const getFieldsToShow = (
  formulaChainId: number | null,
  rangeFieldsData: GoalCycleRangeFields | undefined,
  requiredFields: string[],
) => {
  if (!formulaChainId || !rangeFieldsData) {
    return INPUT_FIELDS_CONFIG.filter(field => field.required);
  }

  const requiredFieldsSet = new Set(requiredFields);
  return INPUT_FIELDS_CONFIG.filter(
    field => field.required || requiredFieldsSet.has(field.fieldName),
  );
};

/**
 * Creates a configured value input component with validation
 */
const createValueInput = (
  label: string,
  fieldName: Boundary,
  // biome-ignore lint/suspicious/noExplicitAny: out of scope
  rules: any,
  validateSequence?: (fieldName: Boundary, value: string | number) => void,
) => (
  <HuFormInputClassic
    aria-label={`${label} value input`}
    key={fieldName}
    name={fieldName}
    rules={{
      ...rules,
      ...(validateSequence && {
        validate: (value: string | number) =>
          validateSequence(fieldName, value),
      }),
    }}
    inputProps={{
      showClear: false,
      label: label,
      type: 'number',
      fullWidth: true,
      size: 'small',
      hasCounter: false,
    }}
  />
);

const ValueInputsAndFormula = () => {
  const { t } = useLokaliseTranslation('goals');
  const HuGoThemeProvider = useHuGoTheme();
  const { setValue, control } = useFormContext();

  const formulaChain = useWatch({ control, name: 'formulaChain' });
  const goalId = useWatch({ control, name: 'goalId' });
  const goalCycle = useWatch({ control, name: 'goalCycle' });

  const isCycleInProgress = isGoalCycleInProgressStatus(goalCycle?.status);
  const isFormulaDisabled = !!(goalId && isCycleInProgress);
  const formulaChainId = formulaChain?.value || null;

  const { data: rangeFieldsData, isLoading: isRangeFieldsLoading } = useQuery(
    goalsKeys.allRangeFields(formulaChainId),
    () => getGoalCycleRangeFields(formulaChainId),
    {
      enabled: !!formulaChainId,
      select: res => res.data,
    },
  );

  const requiredFields = rangeFieldsData?.requiredFields || [];
  const fieldsToShow = getFieldsToShow(
    formulaChainId,
    rangeFieldsData,
    requiredFields,
  );
  const activeFieldNames = fieldsToShow.map(field => field.fieldName);

  const { requiredRules, optionalRules, validateSequence } =
    useValueInputRules(activeFieldNames);

  const handleFormulaChange = (option: FormulaOption | null) => {
    setValue('formulaChain', option ?? null, { shouldDirty: true });
  };

  const inputs = useMemo(() => {
    return fieldsToShow.map(field =>
      createValueInput(
        t(field.labelKey),
        field.fieldName,
        field.required ? requiredRules : optionalRules,
        validateSequence,
      ),
    );
  }, [fieldsToShow, t, requiredRules, optionalRules, validateSequence]);

  const shouldShowFormula = goalCycle?.hasFormulas ?? false;

  const shouldShowInputs = shouldShowFormula ? !isNil(formulaChain) : true;

  return (
    <HuGoThemeProvider>
      <Stack sx={{ gap: 3 }}>
        {shouldShowFormula && (
          <Stack sx={{ gap: 2 }}>
            <Stack
              flexDirection="row"
              alignItems="center"
              sx={{ gap: 1 }}
            >
              <Typography
                variant="globalS"
                fontWeight="fontWeightSemiBold"
                color="new.text.neutral.default"
              >
                {t('new.how_measure_progress')}
              </Typography>
              <HuTooltip
                title={t('new.measure_progress_tooltip')}
                direction="right"
              >
                <InfoOutlinedIcon
                  sx={{ cursor: 'pointer', width: 16, height: 16 }}
                />
              </HuTooltip>
            </Stack>

            <FormulasAutocomplete
              value={formulaChain || null}
              onChange={handleFormulaChange}
              disabled={isRangeFieldsLoading || isFormulaDisabled}
            />
          </Stack>
        )}

        {shouldShowInputs && (
          <Stack
            sx={{
              display: 'grid',
              gridTemplateColumns: {
                xs: '1fr',
                sm: 'repeat(2, 1fr)',
              },
              rowGap: 3,
              columnGap: 2,
            }}
            role="group"
            aria-label="Goal value inputs"
          >
            {inputs.map(input => (
              <Stack key={`input-${input.key}`}>{input}</Stack>
            ))}
          </Stack>
        )}
      </Stack>
    </HuGoThemeProvider>
  );
};

export default ValueInputsAndFormula;
