import { useEffect, useMemo, useState } from 'react';

import { Location } from '@osrd-project/ui-icons';
import { compact } from 'lodash';
import { useTranslation } from 'react-i18next';
import nextId from 'react-id-generator';
import { useSelector } from 'react-redux';

import IntermediatePointIcon from 'assets/pictures/mapMarkers/intermediate-point.svg';
import { useOsrdConfSelectors, useOsrdConfActions } from 'common/osrdContext';
import type { StdcmConfSliceActions } from 'reducers/osrdconf/stdcmConf';
import type { PathStep } from 'reducers/osrdconf/types';
import { useAppDispatch } from 'store';
import { addElementAtIndex, replaceElementAtIndex } from 'utils/array';
import { formatDurationAsISO8601 } from 'utils/timeManipulation';

import StdcmCard from './StdcmCard';
import StdcmDefaultCard from './StdcmDefaultCard';
import StdcmInputVia from './StdcmInputVia';
import StdcmOperationalPoint from './StdcmOperationalPoint';
import StdcmStopType from './StdcmStopType';
import { StdcmStopTypes } from '../../types';
import type { StdcmConfigCardProps } from '../../types';

const generateUniqueId = (idsList: string[]): string => {
  let id;
  do {
    id = nextId();
  } while (idsList.includes(id));
  return id;
};

const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => {
  const { t } = useTranslation('stdcm');
  const dispatch = useAppDispatch();
  const { getPathSteps } = useOsrdConfSelectors();
  const { deleteVia, updatePathSteps, updateViaStopTime } =
    useOsrdConfActions() as StdcmConfSliceActions;
  const pathSteps = useSelector(getPathSteps);

  const [stopTypes, setStopTypes] = useState<Record<string, StdcmStopTypes>>(
    compact(pathSteps).reduce(
      (acc, cur) => {
        acc[cur.id] = cur.stopType || StdcmStopTypes.PASSAGE_TIME;
        return acc;
      },
      {} as Record<string, StdcmStopTypes>
    )
  );

  const intermediatePoints = useMemo(() => pathSteps.slice(1, -1), [pathSteps]);

  const updatePathStepsList = (pathStep: PathStep | null, index: number) => {
    if (!pathStep) return;
    const newPathSteps = replaceElementAtIndex(pathSteps, index, pathStep);
    dispatch(updatePathSteps({ pathSteps: newPathSteps }));
  };

  const updatePathStepStopTime = (stopTime: string, index: number, pathStepId: string) => {
    const pathStepToUpdate = pathSteps[index];
    if (!pathStepToUpdate) return;
    dispatch(
      updateViaStopTime({
        via: pathStepToUpdate,
        duration: formatDurationAsISO8601(Number(stopTime) * 60),
        stopType: stopTypes[pathStepId],
      })
    );
  };

  const updateStopType = (newStopType: StdcmStopTypes, index: number, pathStepId: string) => {
    setStopTypes((prevStopTypes) => ({
      ...prevStopTypes,
      [pathStepId]: newStopType,
    }));
    const defaultStopTime = newStopType === StdcmStopTypes.DRIVER_SWITCH ? '3' : '';
    updatePathStepStopTime(defaultStopTime, index, pathStepId);
  };

  const deleteViaOnClick = (index: number, pathStepId: string) => {
    setStopTypes((prevStopTypes) => {
      delete prevStopTypes[pathStepId];
      return prevStopTypes;
    });
    dispatch(deleteVia(index));
  };

  const addViaOnClick = (pathStepIndex: number) => {
    const newPathStepId = generateUniqueId(pathSteps.map((pathStep) => pathStep?.id || ''));
    const newPathSteps = addElementAtIndex(pathSteps, pathStepIndex, {
      id: newPathStepId,
      uic: -1,
    });
    setStopTypes((prevStopTypes) => ({
      ...prevStopTypes,
      [newPathStepId]: StdcmStopTypes.PASSAGE_TIME,
    }));
    dispatch(updatePathSteps({ pathSteps: newPathSteps }));
  };

  useEffect(() => {
    pathSteps.forEach((pathStep, index) => {
      if (pathStep) {
        const stopType = stopTypes[pathStep.id];
        if (stopType && pathStep.stopType !== stopType) {
          const updatedPathStep = {
            ...pathStep,
            stopType,
          };
          updatePathStepsList(updatedPathStep, index);
        }
      }
    });
  }, [stopTypes, pathSteps]);

  return (
    <div className="stdcm-vias-list">
      {intermediatePoints.length > 0 &&
        compact(intermediatePoints).map((pathStep, index) => {
          const pathStepIndex = index + 1;
          return (
            <div className="stdcm-vias-bundle" key={pathStep.id}>
              <StdcmDefaultCard
                hasTip
                text={t('trainPath.addVia')}
                Icon={<Location size="lg" variant="base" />}
                onClick={() => addViaOnClick(pathStepIndex)}
                disabled={disabled}
              />
              <StdcmCard
                name={t('trainPath.vias')}
                title={
                  <div className="stdcm-via-icons">
                    <div className="icon-bundle mt-1">
                      <img src={IntermediatePointIcon} alt="intermediate-point" />
                      <span className="icon-index">{pathStepIndex}</span>
                    </div>
                    <button type="button" onClick={() => deleteViaOnClick(index, pathStep.id)}>
                      {t('translation:common.delete')}
                    </button>
                  </div>
                }
                hasTip
                disabled={disabled}
                className="via"
              >
                <StdcmOperationalPoint
                  updatePoint={(e) => updatePathStepsList(e, pathStepIndex)}
                  point={pathStep}
                  opPointId={pathStep.id}
                  disabled={disabled}
                />
                {'uic' in pathStep && pathStep.uic !== -1 && (
                  <>
                    <StdcmStopType
                      stopTypes={stopTypes[pathStep.id]}
                      updatePathStepStopType={(newStopType) =>
                        updateStopType(newStopType, pathStepIndex, pathStep.id)
                      }
                    />
                    <StdcmInputVia
                      stopType={stopTypes[pathStep.id]}
                      stopDuration={pathStep.stopFor}
                      updatePathStepStopTime={(e) =>
                        updatePathStepStopTime(e, pathStepIndex, pathStep.id)
                      }
                    />
                  </>
                )}
              </StdcmCard>
            </div>
          );
        })}
      <StdcmDefaultCard
        hasTip
        text={t('trainPath.addVia')}
        Icon={<Location size="lg" variant="base" />}
        onClick={() => addViaOnClick(pathSteps.length - 1)}
        disabled={disabled}
      />
    </div>
  );
};

export default StdcmVias;