'use client';
import { Suspense, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter, useSearchParams } from 'next/navigation';
import { Paper, Skeleton, Stack, Typography } from '@mui/material';
import { AppButton, AppIcon, AppLoading, StepperHeader } from '@/components';
import { ROUTES } from '@/constants';
import { useAuth } from '@/context/auth';
import { useBnplOptions } from '@/services/bnpl';
import { BNPL_QUERY_REQUEST_ID, BNPL_QUERY_TRANSACTION_ID } from '@/services/bnpl/constants';
import { CHECKOUT_QUERY_REQUEST_ID } from '@/services/payment/constants';
import type { BnplEligibilityResult, IssueBnplTokenResult, ProviderCode } from '@/services/bnpl/types';
import MethodStep from './MethodStep';
import PlanStep from './PlanStep';
import EligibilityStep from './EligibilityStep';
import ScheduleStep from './ScheduleStep';

type WizardStep = 'provider' | 'plan' | 'eligibility' | 'schedule';
const STEP_ORDER: WizardStep[] = ['provider', 'plan', 'eligibility', 'schedule'];

/**
 * BNPL installment checkout (D1–D4) — the alternate branch off C6. A single stateful wizard: D1 method /
 * provider → D2 plan → D3 eligibility → D4 schedule + contract, then the provider handoff. On a cleared
 * down-payment the return surface routes to the **reused f9 confirmation** (the booking confirms exactly
 * as the card path). Reached with `?request_id=`; `useSearchParams` needs a Suspense boundary.
 */
export default function BnplCheckoutPage() {
  return (
    <Suspense fallback={<AppLoading />}>
      <BnplCheckoutScreen />
    </Suspense>
  );
}

function BnplCheckoutScreen() {
  const t = useTranslations('bnpl');
  const tb = useTranslations('booking');
  const tc = useTranslations('common');
  const tp = useTranslations('payment');
  const locale = useLocale();
  const router = useRouter();
  const params = useSearchParams();
  const [{ currentUser }] = useAuth();

  const requestId = Number(params.get(BNPL_QUERY_REQUEST_ID));
  const validId = Number.isInteger(requestId) && requestId > 0;
  const { data: options, isLoading, isError, refetch } = useBnplOptions(validId ? requestId : undefined);

  const [step, setStep] = useState<WizardStep>('provider');
  const [providerCode, setProviderCode] = useState<ProviderCode | null>(null);
  const [planId, setPlanId] = useState<string | null>(null);
  const [eligibility, setEligibility] = useState<BnplEligibilityResult | null>(null);

  const toCard = () => router.replace(`/${locale}${ROUTES.CHECKOUT}?${CHECKOUT_QUERY_REQUEST_ID}=${requestId}`);
  const toBookings = () => router.replace(`/${locale}${ROUTES.BOOKINGS}`);
  const toRequest = () => router.replace(`/${locale}${ROUTES.BOOKING_REQUEST_STATUS}/${requestId}`);

  if (!validId) {
    return (
      <MessageCard icon="error" tone="var(--bal-error)" title={t('error_title')} ctaLabel={tb('bd_my_bookings')} onCta={toBookings} />
    );
  }
  if (isError) {
    return <MessageCard icon="error" tone="var(--bal-error)" title={t('error_title')} body={t('error_body')} ctaLabel={tc('retry')} onCta={() => refetch()} />;
  }
  if (isLoading || !options) return <WizardSkeleton />;

  // Only an accepted, awaiting-payment request is payable — converge/explain otherwise (mirrors C6).
  if (options.requestStatus === 'converted') {
    return (
      <MessageCard
        icon="verified"
        tone="var(--bal-success)"
        title={tp('already_paid_title')}
        body={tp('already_paid_body')}
        ctaLabel={tb('converted_cta')}
        onCta={toRequest}
      />
    );
  }
  if (options.requestStatus !== 'accepted_awaiting_payment') {
    const expired = options.requestStatus === 'payment_deadline_expired';
    return (
      <MessageCard
        icon="pending"
        tone="var(--bal-warning)"
        title={expired ? tp('window_expired_title') : tp('not_payable_title')}
        body={expired ? tp('window_expired_body') : undefined}
        ctaLabel={t('pay_with_card')}
        onCta={toCard}
      />
    );
  }

  const returnUrl = (extra?: Record<string, string>) => {
    const query = new URLSearchParams({ [BNPL_QUERY_REQUEST_ID]: String(requestId), ...extra });
    return `/${locale}${ROUTES.CHECKOUT_BNPL_RETURN}?${query.toString()}`;
  };

  const onIssued = (result: IssueBnplTokenResult) => {
    if (!result.redirectUrl) {
      // Nothing to hand off to — read the order directly on the return surface.
      router.push(returnUrl({ [BNPL_QUERY_TRANSACTION_ID]: String(result.bnplTransactionId) }));
      return;
    }
    if (/^https?:\/\//i.test(result.redirectUrl)) {
      // The real provider page — a full navigation outside the app router.
      window.location.assign(result.redirectUrl);
      return;
    }
    router.push(`/${locale}${result.redirectUrl}`);
  };

  const activeProvider = options.providers.find((p) => p.providerCode === providerCode);

  return (
    <Stack sx={{ gap: 2 }}>
      <Stack sx={{ gap: 0.25, alignItems: 'center', textAlign: 'center' }}>
        <Typography variant="h6" component="h1">
          {t('title')}
        </Typography>
      </Stack>

      <StepperHeader
        activeStep={STEP_ORDER.indexOf(step)}
        steps={[t('step_provider'), t('step_plan'), t('step_eligibility'), t('step_schedule')]}
      />

      {step === 'provider' ? (
        <MethodStep
          options={options}
          selectedProvider={providerCode}
          onSelectProvider={setProviderCode}
          onContinue={() => setStep('plan')}
          onPayWithCard={toCard}
        />
      ) : null}

      {step === 'plan' && providerCode && activeProvider ? (
        <PlanStep
          providerCode={providerCode}
          plans={activeProvider.plans}
          selectedPlanId={planId}
          onSelectPlan={setPlanId}
          onContinue={() => setStep('eligibility')}
          onBack={() => setStep('provider')}
        />
      ) : null}

      {step === 'eligibility' && providerCode ? (
        <EligibilityStep
          bookingRequestId={requestId}
          providerCode={providerCode}
          sessionMobile={currentUser?.phone ?? ''}
          initialResult={eligibility}
          onApproved={(result) => {
            setEligibility(result);
            setStep('schedule');
          }}
          onPayWithCard={toCard}
        />
      ) : null}

      {step === 'schedule' && providerCode && planId ? (
        <ScheduleStep
          bookingRequestId={requestId}
          providerCode={providerCode}
          planId={planId}
          onBack={() => setStep('eligibility')}
          onIssued={onIssued}
          onConverged={() => router.replace(returnUrl())}
        />
      ) : null}
    </Stack>
  );
}

function MessageCard({
  icon,
  tone,
  title,
  body,
  ctaLabel,
  onCta,
}: {
  icon: string;
  tone: string;
  title: string;
  body?: string;
  ctaLabel: string;
  onCta: () => void;
}) {
  return (
    <Paper elevation={0} sx={{ p: 4, textAlign: 'center', border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
      <AppIcon icon={icon} size={44} color={tone} />
      <Typography variant="subtitle1" sx={{ fontWeight: 700, mt: 1, mb: body ? 0.5 : 2 }}>
        {title}
      </Typography>
      {body ? (
        <Typography variant="body2" sx={{ color: 'text.secondary', mb: 2 }}>
          {body}
        </Typography>
      ) : null}
      <AppButton variant="contained" color="primary" onClick={onCta}>
        {ctaLabel}
      </AppButton>
    </Paper>
  );
}

function WizardSkeleton() {
  return (
    <Stack sx={{ gap: 2 }}>
      <Skeleton variant="text" width="50%" height={32} sx={{ mx: 'auto' }} />
      <Skeleton variant="rounded" height={48} />
      <Skeleton variant="rounded" height={72} />
      <Skeleton variant="rounded" height={64} />
      <Skeleton variant="rounded" height={64} />
      <Skeleton variant="rounded" height={48} />
    </Stack>
  );
}
