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

import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox';
import Link from '@material-hu/components/design-system/Link';

import { useAuth } from 'src/contexts/JWTContext';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { getCurrentLocale } from 'src/utils/locale';

import { PLAN_INTEREST_RATIO, PLAN_TAX_RATIO } from '../../constants';
import { useMicroloansTermsModal } from '../../contexts/MicroloansTermsModalContext';
import {
  type AcceptanceField,
  type LoanPaymentPlanOption,
  type Periodicity,
} from '../../types';
import {
  formatPaymentDateMX,
  getNextPayrollFridayDateMexico,
  resolvePlanPaymentTotals,
} from '../../utils/formatters';
import { validateBankAccountNumber } from '../../utils/validateBankAccountNumber';

import { BankAccountSection } from './BankAccountSection';
import { ConfirmStepContactCard } from './ConfirmStepContactCard';
import { ConfirmStepSchedulePanel } from './ConfirmStepSchedulePanel';
import { ConfirmStepSummaryColumn } from './ConfirmStepSummaryColumn';
import { CreditDetailsModal } from './CreditDetailsModal';
import { twoColumnStepGridSx } from './confirmStepSx';
import { type ConfirmStepApiSimulation } from './confirmStepTypes';
import { RequestOfferActions } from './RequestOfferActions';

export type { ConfirmStepApiSimulation };

export type ConfirmStepProps = {
  selectedAmount: number;
  selectedWeeks: number;
  /** Simulated plan row for the selected term; avoids hardcoded 4/8/12-only totals. */
  selectedPaymentOption?: LoanPaymentPlanOption;
  onBack: () => void;
  onAccept: () => void | Promise<void>;
  confirmSimulation?: ConfirmStepApiSimulation;
  acceptInFlight?: boolean;
  acceptDisabled?: boolean;
  loanReason: string;
  onLoanReasonChange: (value: string) => void;
  loanReasonComment: string;
  onLoanReasonCommentChange: (value: string) => void;
  tnaPercent?: number;
  loanTermsAccepted: boolean;
  onLoanTermsAcceptedChange: (accepted: boolean) => void;
  requiredAcceptanceFields: AcceptanceField[];
  periodicity: Periodicity;
  bankFound?: boolean;
  bankAccountNumberValid?: boolean;
};

type CreditDetailsMode = 'closed' | 'simulation' | 'estimate';

export const ConfirmStep = ({
  selectedAmount,
  selectedWeeks,
  selectedPaymentOption,
  onBack,
  onAccept,
  confirmSimulation,
  acceptInFlight = false,
  acceptDisabled = false,
  loanReason,
  onLoanReasonChange,
  loanReasonComment,
  onLoanReasonCommentChange,
  tnaPercent,
  loanTermsAccepted,
  onLoanTermsAcceptedChange,
  requiredAcceptanceFields,
  periodicity,
  bankFound,
  bankAccountNumberValid,
}: ConfirmStepProps) => {
  const showBankAccountInput =
    requiredAcceptanceFields.includes('bankAccountNumber');
  const { t } = useLokaliseTranslation('loans');
  const { user } = useAuth();
  const locale = useMemo(() => getCurrentLocale(user), [user]);
  const { openTermsModal } = useMicroloansTermsModal();
  const [creditDetailsMode, setCreditDetailsMode] =
    useState<CreditDetailsMode>('closed');

  const openSimulationDetails = useCallback(() => {
    setCreditDetailsMode('simulation');
  }, []);

  const openEstimateDetails = useCallback(() => {
    setCreditDetailsMode('estimate');
  }, []);

  const closeCreditDetails = useCallback(() => {
    setCreditDetailsMode('closed');
  }, []);

  const totals = resolvePlanPaymentTotals(
    selectedAmount,
    selectedWeeks,
    selectedPaymentOption,
  );
  const extraCost = Math.max(0, totals.total - selectedAmount);
  const totalInterest = Math.round(extraCost * PLAN_INTEREST_RATIO * 100) / 100;
  const totalTax = Math.round(extraCost * PLAN_TAX_RATIO * 100) / 100;

  const scheduleTotals = confirmSimulation
    ? {
        weekly: confirmSimulation.weeklyPaymentMxn,
        total: confirmSimulation.totalToRepayMxn,
      }
    : totals;

  const summaryPrincipal = confirmSimulation?.principalMxn ?? selectedAmount;

  const onCreditDetailsOpen = confirmSimulation
    ? openSimulationDetails
    : openEstimateDetails;

  const schedule = useMemo(() => {
    if (confirmSimulation?.installments?.length) {
      return confirmSimulation.installments;
    }
    const first = getNextPayrollFridayDateMexico();
    const y = first.getUTCFullYear();
    const m = first.getUTCMonth();
    const d = first.getUTCDate();
    return Array.from({ length: selectedWeeks }, (_, idx) => {
      const date = new Date(Date.UTC(y, m, d + idx * 7, 12, 0, 0));
      return {
        week: idx + 1,
        dateLabel: formatPaymentDateMX(date, locale),
        paymentMxn: scheduleTotals.weekly,
      };
    });
  }, [
    confirmSimulation?.installments,
    locale,
    scheduleTotals.weekly,
    selectedWeeks,
  ]);

  const disclosureTna =
    confirmSimulation?.tnaPercent ?? tnaPercent ?? undefined;

  const getCreditDetailsTotalInterests = () => {
    if (creditDetailsMode === 'simulation' && confirmSimulation) {
      return confirmSimulation.costMxn;
    }
    if (creditDetailsMode === 'estimate') {
      return totalInterest + totalTax;
    }
    return 0;
  };
  const creditDetailsTotalInterests = getCreditDetailsTotalInterests();

  const creditDetailsCatPercent =
    creditDetailsMode === 'simulation'
      ? confirmSimulation?.catPercent
      : undefined;

  return (
    <Stack sx={{ gap: 4, width: '100%' }}>
      <Stack sx={{ ...twoColumnStepGridSx, gap: { xs: 6 } }}>
        <ConfirmStepSummaryColumn
          summaryPrincipal={summaryPrincipal}
          selectedWeeks={selectedWeeks}
          scheduleTotals={scheduleTotals}
          onCreditDetailsOpen={onCreditDetailsOpen}
          periodicity={periodicity}
        />
        <Stack
          sx={{
            gap: 2,
            minWidth: 0,
            width: '100%',
          }}
        >
          <ConfirmStepContactCard
            loanReason={loanReason}
            onLoanReasonChange={onLoanReasonChange}
            loanReasonComment={loanReasonComment}
            onLoanReasonCommentChange={onLoanReasonCommentChange}
          />
          {showBankAccountInput && (
            <BankAccountSection
              translations={{
                label: t('clabe.label'),
                placeholder: t('clabe.placeholder'),
                helperText: t('clabe.helper'),
                errorRequired: t('clabe.errorRequired'),
                errorInvalid: t('clabe.errorInvalid'),
                title: t('clabe.title'),
                bankLabel: t('clabe.bank_label'),
                bankPlaceholder: t('clabe.bank_placeholder'),
                bankErrorRequired: t('clabe.bank_error'),
                bankErrorMinLength: t('clabe.bank_error_min_length'),
              }}
              validate={value =>
                validateBankAccountNumber(value) || t('clabe.errorInvalid')
              }
              bankFound={bankFound}
              bankAccountNumberValid={bankAccountNumberValid}
            />
          )}
          <ConfirmStepSchedulePanel
            schedule={schedule}
            selectedWeeks={selectedWeeks}
            periodicity={periodicity}
          />
          <Typography
            component="p"
            variant="globalXS"
            sx={{
              color: theme => theme.palette.new.text.neutral.lighter,
              lineHeight: 1.5,
              textAlign: 'justify',
            }}
          >
            {t('status.disclaimer')}
          </Typography>
          <HuCheckbox
            checked={loanTermsAccepted}
            onChange={() => onLoanTermsAcceptedChange(!loanTermsAccepted)}
            label={
              <Typography
                component="span"
                variant="globalXS"
                sx={{
                  color: theme => theme.palette.new.text.neutral.lighter,
                  lineHeight: 1.5,
                  display: 'flex',
                  alignItems: 'center',
                  gap: 0.5,
                }}
              >
                {t('confirm.accept_terms_lead')}
                <Link
                  component="button"
                  type="button"
                  underline="hover"
                  aria-label={t('legal.terms_aria')}
                  onClick={event => {
                    event.preventDefault();
                    event.stopPropagation();
                    openTermsModal('requestOffer');
                  }}
                  sx={{
                    fontWeight: 'fontWeightSemiBold',
                  }}
                >
                  {t('confirm.accept_terms_link')}
                </Link>
              </Typography>
            }
          />
        </Stack>
      </Stack>

      <CreditDetailsModal
        open={creditDetailsMode !== 'closed'}
        onClose={closeCreditDetails}
        principal={summaryPrincipal}
        totalInterests={creditDetailsTotalInterests}
        totalToPay={scheduleTotals.total}
        catPercent={creditDetailsCatPercent}
        tnaPercent={disclosureTna}
        installmentsCount={selectedWeeks}
        periodicity={periodicity}
      />

      <RequestOfferActions
        layout="row"
        justifyContent="flex-end"
        sx={{
          display: { sm: 'grid' },
          gridAutoFlow: 'column',
          gridAutoColumns: '1fr',
          width: { sm: 'fit-content' },
          ml: { sm: 'auto' },
        }}
        actions={[
          {
            label: t('back'),
            variant: 'secondary',
            fullWidth: false,
            onClick: onBack,
          },
          {
            label: t('confirm.accept'),
            variant: 'primary',
            fullWidth: false,
            onClick: () => {
              void onAccept();
            },
            disabled: acceptInFlight || acceptDisabled,
            sx: {
              bgcolor: theme =>
                theme.palette.new.action.button.background.success.default,
              color: theme =>
                theme.palette.new.action.button.text.primary.default,
              '&:hover': {
                bgcolor: theme =>
                  theme.palette.new.action.button.background.success.hover,
              },
            },
          },
        ]}
      />
    </Stack>
  );
};
