'use client';
import { Suspense, useRef } 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,
  CountdownTimer,
  EscrowNotice,
  PriceBreakdown,
  StatusChip,
} from '@/components';
import AppAlert from '@/components/common/AppAlert';
import { ROUTES } from '@/constants';
import { ApiError } from '@/lib/api/errors';
import { formatShamsiDate, localeTag } from '@/utils';
import { useCheckoutSummary, useInitiatePayment } from '@/services/payment';
import {
  BNPL_ENABLED,
  CHECKOUT_QUERY_REQUEST_ID,
  CHECKOUT_QUERY_TRANSACTION_ID,
} from '@/services/payment/constants';
import type { CheckoutSummaryDto } from '@/services/payment/types';

/**
 * C6 — خلاصه و پرداخت (summary & pay). The acceptance badge, the served & reconciling
 * service-cost / commission / VAT / total breakdown, the load-bearing escrow trust notice, and the
 * «ادامه پرداخت ←» CTA that initiates the card payment and follows the gateway redirect. Reached from
 * C5's accept CTA with `?request_id=`. `useSearchParams` needs a Suspense boundary.
 */
export default function CheckoutPage() {
  return (
    <Suspense fallback={<AppLoading />}>
      <CheckoutScreen />
    </Suspense>
  );
}

function CheckoutScreen() {
  const t = useTranslations('payment');
  const tb = useTranslations('booking');
  const tc = useTranslations('common');
  const locale = useLocale();
  const router = useRouter();
  const params = useSearchParams();

  const requestId = Number(params.get(CHECKOUT_QUERY_REQUEST_ID));
  const validId = Number.isInteger(requestId) && requestId > 0;
  const { data: summary, isLoading, isError, refetch } = useCheckoutSummary(validId ? requestId : undefined);
  const initiate = useInitiatePayment();

  // One idempotency key per payment ATTEMPT: created lazily on the first tap and reused across retries
  // of the same attempt (double-tap, transient network error). A new attempt — after a failed outcome the
  // user comes back to a fresh mount of this screen — gets a new key.
  const attemptKeyRef = useRef<string | null>(null);

  // A malformed/missing request_id can never load — navigation, not a retry that would fire
  // `checkout_summary/undefined` (a manual refetch() bypasses the query's `enabled` gate).
  if (!validId) {
    return (
      <MessageCard
        icon="error"
        tone="var(--bal-error)"
        title={t('error_title')}
        body={t('invalid_link_body')}
        ctaLabel={tb('bd_my_bookings')}
        onCta={() => router.replace(`/${locale}${ROUTES.BOOKINGS}`)}
      />
    );
  }
  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 || !summary) return <CheckoutSkeleton />;

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

  // Anything other than "awaiting payment" cannot show a pay CTA — converge or explain instead.
  if (summary.requestStatus === 'converted') {
    return (
      <MessageCard
        icon="verified"
        tone="var(--bal-success)"
        title={t('already_paid_title')}
        body={t('already_paid_body')}
        ctaLabel={tb('converted_cta')}
        onCta={() => router.replace(returnUrl())}
      />
    );
  }
  if (summary.requestStatus !== 'accepted_awaiting_payment') {
    const expired = summary.requestStatus === 'payment_deadline_expired';
    return (
      <MessageCard
        icon="pending"
        tone="var(--bal-warning)"
        title={expired ? t('window_expired_title') : t('not_payable_title')}
        body={expired ? t('window_expired_body') : undefined}
        ctaLabel={t('back_to_request')}
        onCta={() => router.replace(`/${locale}${ROUTES.BOOKING_REQUEST_STATUS}/${requestId}`)}
      />
    );
  }

  const handlePay = () => {
    attemptKeyRef.current ??= crypto.randomUUID();
    initiate.mutate(
      { bookingRequestId: requestId, idempotencyKey: attemptKeyRef.current },
      {
        onSuccess: (result) => {
          if (!result.redirectUrl) {
            // No gateway hop to make — read the outcome directly.
            router.push(returnUrl({ [CHECKOUT_QUERY_TRANSACTION_ID]: String(result.transactionId) }));
            return;
          }
          if (/^https?:\/\//i.test(result.redirectUrl)) {
            // The real PSP page — a full navigation, outside the app router.
            window.location.assign(result.redirectUrl);
            return;
          }
          router.push(`/${locale}${result.redirectUrl}`);
        },
        onError: (error) => {
          if (error instanceof ApiError && error.status === 409) {
            // "Already paid / already in progress / window lapsed" — benign convergence, never a toast:
            // the return surface reads the actual outcome and routes accordingly.
            router.replace(returnUrl());
          }
        },
      },
    );
  };

  const busy = initiate.isPending || initiate.isSuccess;
  // ApiError.message is a raw server/network string, never localized — always show the i18n copy.
  const inlineError =
    initiate.error && !(initiate.error instanceof ApiError && initiate.error.status === 409)
      ? t('initiate_failed')
      : null;

  return (
    <Stack sx={{ gap: 3 }}>
      <Stack sx={{ gap: 1, alignItems: 'center', textAlign: 'center' }}>
        <StatusChip status="verified" label={tb('accepted_badge')} />
        <Typography variant="h6" component="h1">
          {t('title_checkout')}
        </Typography>
      </Stack>

      <EngagementSummary summary={summary} locale={locale} />

      {summary.paymentDeadlineAt ? (
        <Paper elevation={0} sx={{ p: 2, borderRadius: 2, border: '1px solid', borderColor: 'divider' }}>
          <CountdownTimer
            deadlineIso={summary.paymentDeadlineAt}
            label={tb('payment_countdown_label')}
            elapsedText={tb('payment_elapsed')}
            urgent
            onElapsed={() => refetch()}
          />
        </Paper>
      ) : null}

      <PriceBreakdown
        rows={[
          {
            key: 'service_cost',
            // Quantity context per the wireframe («هزینه خدمت (۸ ساعت)») — the visit count is the only
            // quantity that always matches the charged gross (variant price × session count).
            label: t('row_service_cost_with_count', { count: summary.sessionCount }),
            amountIrr: summary.serviceCostIrr,
          },
          { key: 'commission', label: t('row_commission'), amountIrr: summary.commissionIrr },
          { key: 'vat', label: t('row_vat'), amountIrr: summary.vatIrr },
        ]}
        totalLabel={t('row_total')}
        totalAmountIrr={summary.totalIrr}
      />

      <EscrowNotice />

      {inlineError ? (
        <AppAlert severity="error" variant="outlined" sx={{ marginY: 0 }}>
          {inlineError}
        </AppAlert>
      ) : null}

      <Stack sx={{ gap: 1 }}>
        <AppButton
          color="secondary"
          variant="contained"
          size="large"
          disabled={busy}
          onClick={handlePay}
          sx={{ py: 1.25 }}
        >
          {initiate.isPending ? t('state_initiating') : initiate.isSuccess ? t('state_redirecting') : t('cta_pay')}
        </AppButton>
        {/* The f11 BNPL branch (D1): «پرداخت اقساطی» → the installment wizard, reached with `?request_id=`. */}
        {BNPL_ENABLED ? (
          <AppButton
            variant="outlined"
            color="secondary"
            startIcon="installments"
            onClick={() => router.push(`/${locale}${ROUTES.CHECKOUT_BNPL}?${CHECKOUT_QUERY_REQUEST_ID}=${requestId}`)}
          >
            {t('bnpl_option')}
          </AppButton>
        ) : null}
      </Stack>
    </Stack>
  );
}

/** Nurse/service/schedule mini-summary — page-only composition (C6 needs no address or price-per-unit). */
function EngagementSummary({ summary, locale }: { summary: CheckoutSummaryDto; locale: string }) {
  const start = new Date(`${summary.requestedDate}T${summary.requestedTimeStart}`);
  const end = new Date(`${summary.requestedDate}T${summary.requestedTimeEnd}`);
  const timeFmt = new Intl.DateTimeFormat(localeTag(locale), {
    hour: '2-digit',
    minute: '2-digit',
  });
  return (
    <Paper elevation={0} sx={{ p: 2.5, borderRadius: 2, border: '1px solid', borderColor: 'divider' }}>
      <Stack sx={{ gap: 0.5 }}>
        <Typography variant="subtitle2" sx={{ fontWeight: 700 }}>
          {summary.variantLabel}
        </Typography>
        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {summary.nurseName} · {summary.patientName}
        </Typography>
        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {formatShamsiDate(start, locale)} · {timeFmt.format(start)} – {timeFmt.format(end)}
        </Typography>
      </Stack>
    </Paper>
  );
}

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 CheckoutSkeleton() {
  return (
    <Stack sx={{ gap: 3 }}>
      <Stack sx={{ gap: 1, alignItems: 'center' }}>
        <Skeleton variant="rounded" width={140} height={24} />
        <Skeleton variant="text" width="50%" height={32} />
      </Stack>
      <Skeleton variant="rounded" height={96} />
      <Skeleton variant="rounded" height={64} />
      <Skeleton variant="rounded" height={160} />
      <Skeleton variant="rounded" height={56} />
      <Skeleton variant="rounded" height={48} />
    </Stack>
  );
}
