import type { MockCode } from '../../bluetooth/readMeter';
import type { ReadStrategy } from '../../parsing/ReadStrategy';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { View } from 'react-native';
import ReadingResult from './components/ReadingResult';
import RetryTakingReading from './components/RetryTakingReading';
import TakingReading from './components/TakingReading';
import ParcialReading from './components/ParcialReading';
import { STEPS } from './constants';
import styles from './styles';
import NoProbeWrapper from '../NoProbeWrapper';

interface StepsTranslations {
  probeReadyToReadTitle: string;
  probeReadyToReadDescription: string;
  probeReadyToReadTextButton: string;
  takingReadingTitle: string;
  takingReadingDescription: string;
  takingReadingTextButton: string;
  readingResultTitle: string;
  readingResultTextButton: string;
  retryTakingReadingTitle: string;
  retryTakingReadingTextButton: string;
  meterFamilyTypePrepositionBadge: string;
  genericErrorInTakingReading: string;
  timeoutError: string;
}

interface ParcialReadingTranslations {
  probeReadyToReadTitle: string;
  probeReadyToReadDescription: string;
  probeReadyToReadTextButton: string;
  takingReadingTitle: string;
  takingReadingDescription: string;
  takingReadingTextButton: string;
  meterFamilyTypePrepositionBadge: string;
  timeoutError: string;
}

interface ReadingTimeouts {
  maxWaitTimePerProbeInteraction: number;
  probeReadingTimeoutInMilliseconds: number;
}

interface Props {
  onClose: Function;
  translations: StepsTranslations;
  onSuccess: Function;
  loadingCurrentDevice: boolean;
  mockCode?: MockCode;
  readStrategy: ReadStrategy;
  reconnectionOrLinkWithProbeTranslations: any;
  goToProbeProbePairing: Function;
  readingDisabled: boolean;
  recoverMeterNumber?: Function | undefined;
  skipReadingResult?: boolean | undefined;
  parcialReadingWithProbeTranslations?: ParcialReadingTranslations | undefined;
  children?: any;
  timeoutRef?: any;
  readingTimeouts?: ReadingTimeouts | undefined;
  meterTypeCode: string | undefined;
  showFamilyBadgeLibrary: boolean;
}

const ProbeReading = ({
  onClose,
  translations,
  onSuccess,
  loadingCurrentDevice,
  readStrategy,
  mockCode,
  reconnectionOrLinkWithProbeTranslations,
  goToProbeProbePairing,
  readingDisabled,
  recoverMeterNumber,
  skipReadingResult = false,
  parcialReadingWithProbeTranslations,
  children,
  timeoutRef,
  readingTimeouts,
  meterTypeCode,
  showFamilyBadgeLibrary = true,
}: Props) => {
  const [currentStep, setCurrentStep] = useState(
    recoverMeterNumber ? ParcialReading.name : TakingReading.name,
  );
  const [readingResult, setReadingResult] = useState(null);
  const [error, setError] = useState('');

  const meterFamilyType = readStrategy.name;

  const onError = useCallback(
    ({ message }) => {
      setError(message ?? translations.genericErrorInTakingReading);
    },
    [translations.genericErrorInTakingReading],
  );

  useEffect(() => {
    if ((readingResult != null || error) && skipReadingResult) {
      if (!error) {
        onSuccess(readingResult);
      } else {
        onClose(error);
      }
    }
  }, [readingResult, error, skipReadingResult, onSuccess, onClose]);

  const stepProps = useMemo(
    () => ({
      [ParcialReading.name]: {
        onPress: () => setCurrentStep(TakingReading.name),
        translations: parcialReadingWithProbeTranslations,
        closeProbeReading: onClose,
        meterFamilyType,
        setReadingResult,
        onError,
        mockCode,
        readStrategy,
        loadingCurrentDevice,
        readingDisabled,
        recoverMeterNumber,
        children,
        timeoutRef,
        readingTimeouts,
        showFamilyBadgeLibrary,
      },
      [TakingReading.name]: {
        translations,
        closeProbeReading: onClose,
        meterFamilyType,
        setReadingResult,
        onError,
        mockCode,
        readStrategy,
        loadingCurrentDevice,
        readingDisabled,
        recoverMeterNumber,
        children,
        timeoutRef,
        readingTimeouts,
        meterTypeCode,
        showFamilyBadgeLibrary,
      },
      [RetryTakingReading.name]: {
        onPress: () => setCurrentStep(TakingReading.name),
        translations,
        meterFamilyType,
        children,
        showFamilyBadgeLibrary,
      },
    }),
    [
      parcialReadingWithProbeTranslations,
      onClose,
      meterFamilyType,
      onError,
      mockCode,
      readStrategy,
      loadingCurrentDevice,
      meterTypeCode,
      readingDisabled,
      recoverMeterNumber,
      children,
      timeoutRef,
      readingTimeouts,
      translations,
      showFamilyBadgeLibrary,
    ],
  );

  const CurrentStepComponent = useMemo(() => {
    if (!STEPS[currentStep]) {
      return () => null;
    }
    return STEPS[currentStep];
  }, [currentStep]);
  if ((readingResult != null || error) && !skipReadingResult) {
    return (
      <View style={styles.container}>
        <ReadingResult
          translations={translations}
          closeProbeReading={onClose}
          meterFamilyType={meterFamilyType}
          error={error}
          onSuccess={onSuccess}
          readingResult={readingResult}
          showFamilyBadgeLibrary={showFamilyBadgeLibrary}
        />
      </View>
    );
  } else {
    return (
      <NoProbeWrapper
        reconnectionOrLinkWithProbeTranslations={reconnectionOrLinkWithProbeTranslations}
        goToProbeProbePairing={goToProbeProbePairing}
      >
        <View style={styles.container}>
          <CurrentStepComponent {...stepProps[currentStep]} />
        </View>
      </NoProbeWrapper>
    );
  }
};

export default ProbeReading;
