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

import Stack from '@material-hu/mui/Stack';
import { type SxProps, type Theme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

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

import {
  buildLoanPlanAnalyticsPayload,
  trackLoanAmountSelected,
  trackLoanPlanSelected,
} from '../../track';
import {
  type LoanOffer,
  type LoanPaymentPlan,
  type LoanPaymentPlanOption,
} from '../../types';
import { isAmountWithinOfferBounds } from '../../utils/buildLoanPaymentPlan';
import { periodicityKey } from '../../utils/periodicity';
import HistoryLink from '../HistoryLink';

import { AmountStep } from './AmountStep';
import { PlanStep } from './PlanStep';
import { RequestOfferActions } from './RequestOfferActions';

function paymentPlanOptionsForPlanStep(
  isPaymentPlanLoading: boolean,
  paymentPlan: LoanPaymentPlan | undefined,
  isAmountValid: boolean,
  amountInBounds: boolean,
): readonly LoanPaymentPlanOption[] | undefined {
  if (isPaymentPlanLoading) {
    return paymentPlan?.options ?? [];
  }
  if (paymentPlan !== undefined) {
    return paymentPlan.options;
  }
  if (isAmountValid && amountInBounds) {
    return [];
  }
  return undefined;
}

function loanPlanSelectionTrackSignature(
  payload: ReturnType<typeof buildLoanPlanAnalyticsPayload>,
): string {
  return `${payload.amount}|${payload.plan_weeks}|${payload.plan_weekly_payment}|${payload.plan_total}`;
}

export type AmountAndPlanStepProps = {
  loanOffer: LoanOffer;
  paymentPlan: LoanPaymentPlan | undefined;
  isPaymentPlanLoading: boolean;

  continueDisabled: boolean;
  selectedAmount: number;
  onAmountChange: (value: number) => void;
  selectedWeeks: number;
  onSelectWeeks: (weeks: number) => void;
  onContinue: () => void;
  onAmountValidityChange?: (valid: boolean) => void;
};

const twoColumnStepGridSx = {
  display: 'grid',
  gridTemplateColumns: {
    xs: '1fr',
    md: 'minmax(0, 1fr) minmax(0, 1fr)',
  },
  gap: { xs: 3, md: 6 },
  width: '100%',
  alignItems: 'start',
  minHeight: '450px',
} as const;

const noEligiblePlansMessageSx: SxProps<Theme> = {
  color: theme => theme.palette.new.text.neutral.lighter,
  py: 2,
};

export const AmountAndPlanStep = ({
  loanOffer,
  paymentPlan,
  isPaymentPlanLoading,
  continueDisabled,
  selectedAmount,
  onAmountChange,
  selectedWeeks,
  onSelectWeeks,
  onContinue,
  onAmountValidityChange,
}: AmountAndPlanStepProps) => {
  const { t } = useLokaliseTranslation('loans');
  const [isAmountValid, setIsAmountValid] = useState(true);
  const lastPlanTrackSignatureRef = useRef<string | null>(null);

  useEffect(() => {
    onAmountValidityChange?.(isAmountValid);
  }, [isAmountValid, onAmountValidityChange]);

  const handleAmountChange = (value: number) => {
    onAmountChange(value);
    trackLoanAmountSelected(value);
  };

  const handleSelectWeeks = (weeks: number) => {
    onSelectWeeks(weeks);
    const payload = buildLoanPlanAnalyticsPayload(
      selectedAmount,
      weeks,
      paymentPlan?.options.find(option => option.weeks === weeks),
    );
    lastPlanTrackSignatureRef.current =
      loanPlanSelectionTrackSignature(payload);
    trackLoanPlanSelected(payload);
  };

  useEffect(() => {
    if (isPaymentPlanLoading) {
      return;
    }
    const opts = paymentPlan?.options;
    if (!opts?.length) {
      return;
    }
    const availableWeeks = new Set(opts.map(option => option.weeks));
    if (!availableWeeks.has(selectedWeeks)) {
      onSelectWeeks(Math.max(...opts.map(option => option.weeks)));
    }
  }, [
    isPaymentPlanLoading,
    onSelectWeeks,
    paymentPlan?.options,
    selectedWeeks,
  ]);

  useEffect(() => {
    if (isPaymentPlanLoading) {
      return;
    }
    const option = paymentPlan?.options?.find(o => o.weeks === selectedWeeks);
    if (!option) {
      return;
    }
    const payload = buildLoanPlanAnalyticsPayload(
      selectedAmount,
      selectedWeeks,
      option,
    );
    const signature = loanPlanSelectionTrackSignature(payload);
    if (lastPlanTrackSignatureRef.current === signature) {
      return;
    }
    lastPlanTrackSignatureRef.current = signature;
    trackLoanPlanSelected(payload);
  }, [isPaymentPlanLoading, paymentPlan, selectedAmount, selectedWeeks]);

  const amountInBounds = isAmountWithinOfferBounds(loanOffer, selectedAmount);

  const hasNoEligiblePlans =
    !isPaymentPlanLoading &&
    isAmountValid &&
    amountInBounds &&
    paymentPlan === undefined;

  const paymentPlanOptionsForStep = paymentPlanOptionsForPlanStep(
    isPaymentPlanLoading,
    paymentPlan,
    isAmountValid,
    amountInBounds,
  );

  const planStepContent = (() => {
    if (hasNoEligiblePlans) {
      return (
        <Typography
          variant="globalM"
          sx={noEligiblePlansMessageSx}
        >
          {t(
            periodicityKey('plan_step.no_plans_message', loanOffer.periodicity),
          )}
        </Typography>
      );
    }
    if (paymentPlanOptionsForStep === undefined) {
      return null;
    }
    return (
      <PlanStep
        selectedWeeks={selectedWeeks}
        onSelectWeeks={handleSelectWeeks}
        onBack={() => undefined}
        onContinue={() => undefined}
        showBack={false}
        showContinueButton={false}
        paymentPlanOptions={paymentPlanOptionsForStep}
        isPaymentPlanLoading={isPaymentPlanLoading}
        periodicity={loanOffer.periodicity}
      />
    );
  })();

  return (
    <Stack sx={{ width: '100%', gap: 4 }}>
      <Stack sx={twoColumnStepGridSx}>
        <Stack sx={{ minWidth: 0, gap: 2 }}>
          <AmountStep
            amountBounds={{
              min: loanOffer.minAmountMxn,
              max: loanOffer.preApprovedMaxAmountMxn,
            }}
            selectedAmount={selectedAmount}
            onAmountChange={handleAmountChange}
            onContinue={() => undefined}
            showContinueButton={false}
            onValidityChange={setIsAmountValid}
            offerWindow={{
              expiresAt: loanOffer.validUntil,
            }}
          />
          <HistoryLink source="request-offer" />
        </Stack>
        <Stack sx={{ minWidth: 0, gap: 2 }}>
          {planStepContent}
          <RequestOfferActions
            layout="row"
            justifyContent="flex-end"
            actions={[
              {
                label: t('continue'),
                variant: 'primary',
                fullWidth: false,
                disabled: continueDisabled,
                onClick: onContinue,
              },
            ]}
          />
        </Stack>
      </Stack>
    </Stack>
  );
};
