import { useCallback, useEffect, useRef, useState } from 'react';
import {
  Box,
  Typography,
  Stack,
  Alert,
  Button,
  Link,
  Divider,
  LinearProgress,
  Skeleton,
  keyframes,
} from '@mui/material';
import CheckIcon from '@mui/icons-material/Check';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import VerifiedUserIcon from '@mui/icons-material/VerifiedUser';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { joinURL } from 'ufo';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import type { TCheckoutSessionExpanded } from '@blocklet/payment-types';
import { usePaymentMethodContext } from '@blocklet/payment-react-headless';

import { getPrefix } from '../../libs/util';
import { formatTokenAmount, primaryContrastColor } from '../utils/format';

// ── Animations ──

const scaleIn = keyframes`
  from { transform: scale(0); opacity: 0; }
  60% { transform: scale(1.15); }
  to { transform: scale(1); opacity: 1; }
`;

const fadeUp = keyframes`
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
`;

// ── Confetti ──

function useConfetti(containerRef: React.RefObject<HTMLElement | null>, enabled: boolean) {
  const firedRef = useRef(false);

  useEffect(() => {
    if (!enabled || firedRef.current || !containerRef.current) return undefined;
    firedRef.current = true;

    const container = containerRef.current;
    const canvas = document.createElement('canvas');
    canvas.style.cssText = 'position:absolute;inset:0;pointer-events:none;z-index:10;';
    canvas.width = container.offsetWidth;
    canvas.height = container.offsetHeight;
    container.appendChild(canvas);

    const ctx = canvas.getContext('2d');
    if (!ctx) return undefined;

    const colors = ['#3b82f6', '#60a5fa', '#34d399', '#fbbf24', '#f472b6', '#a78bfa', '#f97316'];
    const pieces: Array<{
      x: number;
      y: number;
      vx: number;
      vy: number;
      w: number;
      h: number;
      color: string;
      rot: number;
      rv: number;
      opacity: number;
    }> = [];

    for (let i = 0; i < 80; i++) {
      pieces.push({
        x: canvas.width / 2 + (Math.random() - 0.5) * 60,
        y: canvas.height * 0.35,
        vx: (Math.random() - 0.5) * 12,
        vy: -Math.random() * 14 - 4,
        w: Math.random() * 8 + 4,
        h: Math.random() * 6 + 2,
        color: colors[Math.floor(Math.random() * colors.length)],
        rot: Math.random() * Math.PI * 2,
        rv: (Math.random() - 0.5) * 0.3,
        opacity: 1,
      });
    }

    let frame: number;
    const gravity = 0.25;
    const friction = 0.99;

    const animate = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      let alive = false;

      for (const p of pieces) {
        p.vy += gravity;
        p.vx *= friction;
        p.x += p.vx;
        p.y += p.vy;
        p.rot += p.rv;

        if (p.y > canvas.height * 0.6) {
          p.opacity -= 0.02;
        }
        if (p.opacity > 0) {
          alive = true;
          ctx.save();
          ctx.globalAlpha = p.opacity;
          ctx.translate(p.x, p.y);
          ctx.rotate(p.rot);
          ctx.fillStyle = p.color;
          ctx.fillRect(-p.w / 2, -p.h / 2, p.w, p.h);
          ctx.restore();
        }
      }

      if (alive) {
        frame = requestAnimationFrame(animate);
      } else {
        canvas.remove();
      }
    };

    // Small delay so the icon animation plays first
    const timer = setTimeout(() => {
      frame = requestAnimationFrame(animate);
    }, 400);

    return () => {
      clearTimeout(timer);
      cancelAnimationFrame(frame);
      canvas.remove();
    };
  }, [enabled, containerRef]);
}

// ── Types ──

interface VendorInfo {
  success: boolean;
  status: 'delivered' | 'pending' | 'failed';
  progress: number;
  message: string;
  appUrl?: string;
  title?: string;
  name?: string;
  vendorType: string;
}

interface SuccessViewProps {
  submit: {
    vendorStatus: {
      payment_status: string;
      session_status: string;
      vendors: VendorInfo[];
      error: string | null;
      isAllCompleted: boolean;
      hasFailed: boolean;
    } | null;
    result: {
      checkoutSession: TCheckoutSessionExpanded;
    } | null;
  };
  session: TCheckoutSessionExpanded | null | undefined;
}

// ── Helpers ──

function getCustomMessage(session: TCheckoutSessionExpanded | null | undefined): string | undefined {
  return (session as any)?.payment_link?.after_completion?.hosted_confirmation?.custom_message;
}

function getPayee(session: TCheckoutSessionExpanded | null | undefined): string {
  const items = (session as any)?.line_items || [];
  for (const item of items) {
    if (item?.price?.product?.statement_descriptor) {
      return item.price.product.statement_descriptor;
    }
  }
  return (session as any)?.app_name || (session as any)?.payment_link?.app_name || '';
}

function getVendorLabel(vendor: VendorInfo, isFailed: boolean, t: (key: string, params?: any) => string): string {
  const name = vendor.name || vendor.title;
  const isCompleted = vendor.status === 'delivered';

  if (vendor.vendorType === 'didnames') {
    if (isFailed) return t('payment.checkout.vendor.didnames.failed', { name });
    if (isCompleted) return t('payment.checkout.vendor.didnames.completed', { name });
    return t('payment.checkout.vendor.didnames.processing', { name });
  }

  if (isFailed) return t('payment.checkout.vendor.launcher.failed', { name });
  if (isCompleted) return t('payment.checkout.vendor.launcher.completed', { name });
  return t('payment.checkout.vendor.launcher.processing', { name });
}

// ── Hero Icon ──

function HeroSuccessIcon() {
  return (
    <Box
      sx={{
        position: 'relative',
        mb: 1,
        animation: `${scaleIn} 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both`,
      }}>
      <Box
        sx={{
          position: 'absolute',
          inset: -24,
          background: (theme) =>
            theme.palette.mode === 'dark'
              ? 'radial-gradient(circle, rgba(59,130,246,0.12) 0%, transparent 70%)'
              : 'radial-gradient(circle, rgba(59,130,246,0.08) 0%, transparent 70%)',
          borderRadius: '50%',
          pointerEvents: 'none',
        }}
      />
      <Box
        sx={{
          position: 'relative',
          width: { xs: 100, md: 120 },
          height: { xs: 100, md: 120 },
          borderRadius: { xs: '28px', md: '32px' },
          background: (theme) =>
            theme.palette.mode === 'dark'
              ? 'linear-gradient(135deg, rgba(59,130,246,0.15) 0%, rgba(255,255,255,0.04) 100%)'
              : 'linear-gradient(135deg, #eff6ff 0%, #ffffff 100%)',
          border: '1px solid',
          borderColor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(59,130,246,0.2)' : 'rgba(59,130,246,0.12)'),
          boxShadow: (theme) =>
            theme.palette.mode === 'dark'
              ? '0 10px 30px -5px rgba(0,0,0,0.3)'
              : '0 10px 30px -5px rgba(59,130,246,0.1)',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}>
        <Box
          sx={{
            position: 'absolute',
            inset: 0,
            borderRadius: 'inherit',
            background: (theme) =>
              theme.palette.mode === 'dark'
                ? 'linear-gradient(to top-right, rgba(59,130,246,0.1), transparent)'
                : 'linear-gradient(to top-right, rgba(59,130,246,0.06), transparent)',
            pointerEvents: 'none',
          }}
        />
        <VerifiedUserIcon
          sx={{
            fontSize: { xs: 52, md: 64 },
            color: 'primary.main',
            filter: (theme) =>
              theme.palette.mode === 'dark'
                ? 'drop-shadow(0 0 12px rgba(59,130,246,0.4))'
                : 'drop-shadow(0 0 12px rgba(59,130,246,0.2))',
          }}
        />
      </Box>
      <Box
        sx={{
          position: 'absolute',
          bottom: { xs: -6, md: -8 },
          right: { xs: -6, md: -8 },
          width: { xs: 32, md: 38 },
          height: { xs: 32, md: 38 },
          borderRadius: { xs: '12px', md: '14px' },
          bgcolor: 'background.paper',
          boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
          border: '1px solid',
          borderColor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(59,130,246,0.08)'),
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}>
        <CheckCircleIcon sx={{ fontSize: { xs: 20, md: 24 }, color: 'success.main' }} />
      </Box>
    </Box>
  );
}

// ── Payment Receipt (mobile only) ──

function PaymentReceipt({
  session,
  t,
}: {
  session: TCheckoutSessionExpanded | null | undefined;
  t: (key: string, params?: any) => string;
}) {
  const { currencies } = usePaymentMethodContext();
  const amountTotal = (session as any)?.amount_total;
  const currencyId = (session as any)?.currency_id;

  // Skip for trials or no amount
  const subData = (session as any)?.subscription_data;
  if (Number(subData?.trial_period_days || 0) > 0) return null;
  if (!amountTotal || amountTotal === '0') return null;

  // Find currency object from available currencies
  const currency = currencies.find((c) => c.id === currencyId) || null;
  if (!currency) return null;

  const formatted = formatTokenAmount(amountTotal, currency);
  if (!formatted || formatted === '0') return null;

  const amountStr = `${formatted} ${currency.symbol || ''}`.trim();
  // Split the translated sentence around the amount to bold it
  const fullText = t('payment.checkout.completed.summary.paid', { amount: amountStr });
  const idx = fullText.indexOf(amountStr);

  return (
    <Typography
      sx={{
        fontSize: { xs: 15, md: 16 },
        color: 'text.secondary',
        fontWeight: 500,
        lineHeight: 1.6,
        textAlign: 'center',
        maxWidth: 440,
        animation: `${fadeUp} 0.5s ease 0.3s both`,
      }}>
      {idx >= 0 ? (
        <>
          {fullText.slice(0, idx)}
          <Box component="span" sx={{ fontWeight: 700, color: 'text.primary' }}>
            {amountStr}
          </Box>
          {fullText.slice(idx + amountStr.length)}
        </>
      ) : (
        fullText
      )}
    </Typography>
  );
}

// ── Vendor Progress Item ──

function VendorProgressItemV2({ vendor, t }: { vendor: VendorInfo; t: (key: string, params?: any) => string }) {
  const [displayProgress, setDisplayProgress] = useState(0);
  const animationRef = useRef<number>();

  const startAnimation = useCallback(() => {
    const realProgress = vendor.progress || 0;
    let startTime: number;
    let startProgress: number;

    const animate = (currentTime: number) => {
      if (!startTime) {
        startTime = currentTime;
        startProgress = displayProgress;
      }

      const elapsed = currentTime - startTime;
      let newProgress: number;

      if (realProgress === 100) {
        newProgress = 100;
      } else if (realProgress === 0) {
        newProgress = Math.min(startProgress + elapsed / 1000, 99);
      } else if (realProgress > startProgress) {
        const progress = Math.min(elapsed / 1000, 1);
        newProgress = startProgress + (realProgress - startProgress) * progress;
      } else {
        newProgress = Math.min(startProgress + elapsed / 1000, 99);
      }

      newProgress = Math.round(newProgress);
      setDisplayProgress((pre) => Math.min(pre > newProgress ? pre : newProgress, 100));

      if (realProgress === 100) return;
      if (newProgress < 99 && realProgress < 100) {
        animationRef.current = requestAnimationFrame(animate);
      }
    };

    if (animationRef.current) cancelAnimationFrame(animationRef.current);
    animationRef.current = requestAnimationFrame(animate);
  }, [vendor.progress, displayProgress]);

  useEffect(() => {
    startAnimation();
    return () => {
      if (animationRef.current) cancelAnimationFrame(animationRef.current);
    };
  }, [startAnimation]);

  const isCompleted = displayProgress >= 100;
  const isFailed = vendor.status === 'failed';
  const nameText = getVendorLabel(vendor, isFailed, t);

  if (!vendor.name && !vendor.title) {
    return (
      <Box sx={{ mb: 1.5 }}>
        <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 0.75 }}>
          <Skeleton variant="rounded" height={14} width={150} />
          <Skeleton variant="rounded" height={14} width={50} />
        </Stack>
        <Skeleton variant="rounded" height={6} width="100%" />
      </Box>
    );
  }

  return (
    <Box sx={{ mb: 1.5 }}>
      <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 0.75 }}>
        <Typography
          sx={{
            fontSize: 13,
            fontWeight: 600,
            color: isFailed ? 'error.main' : 'text.secondary',
            display: 'flex',
            alignItems: 'center',
          }}>
          {nameText}
          {isCompleted && !isFailed && <CheckIcon sx={{ color: 'success.main', ml: 0.5, fontSize: 16 }} />}
        </Typography>
        {!isCompleted && (
          <Typography sx={{ fontSize: 12, fontWeight: 600, color: isFailed ? 'error.main' : 'text.secondary' }}>
            {t('payment.checkout.vendor.progress', { progress: isFailed ? 0 : displayProgress })}
          </Typography>
        )}
      </Stack>
      <LinearProgress
        variant="determinate"
        value={isFailed ? 100 : displayProgress || 0}
        sx={{
          height: 6,
          borderRadius: 3,
          bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.08)' : 'grey.200'),
          '& .MuiLinearProgress-bar': {
            borderRadius: 3,
            // eslint-disable-next-line no-nested-ternary
            bgcolor: isFailed ? 'error.main' : isCompleted ? 'success.main' : 'primary.main',
            transition: 'background-color 0.3s linear',
          },
        }}
      />
    </Box>
  );
}

// ── Vendor Progress Panel ──

function VendorProgressPanel({
  vendorStatus,
  pageInfo = undefined,
  locale,
  t,
}: {
  vendorStatus: NonNullable<SuccessViewProps['submit']['vendorStatus']>;
  pageInfo?: any;
  locale: string;
  t: (key: string, params?: any) => string;
}) {
  return (
    <Box
      sx={{
        width: '100%',
        maxWidth: 420,
        p: 2.5,
        borderRadius: 3,
        bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.04)' : 'grey.50'),
        border: '1px solid',
        borderColor: 'divider',
        animation: `${fadeUp} 0.5s ease 0.3s both`,
      }}>
      {(vendorStatus.vendors || []).map((vendor, idx) => (
        <VendorProgressItemV2 key={vendor.title || `vendor-${idx}`} vendor={vendor} t={t} />
      ))}
      {vendorStatus.hasFailed && (
        <Typography sx={{ fontSize: 13, fontWeight: 600, color: 'warning.main', mt: 1 }}>
          {t('payment.checkout.vendor.failedMsg')}
        </Typography>
      )}
      {vendorStatus.isAllCompleted && pageInfo?.success_message?.[locale] && (
        <Typography sx={{ fontSize: 14, fontWeight: 600, color: 'text.primary', mt: 1 }}>
          {pageInfo.success_message[locale]}
        </Typography>
      )}
    </Box>
  );
}

// ── Subscription Links ──

function SubscriptionLinks({
  mode,
  subscriptions,
  subscriptionId = undefined,
  payee,
  prefix,
  t,
}: {
  mode: string;
  subscriptions: any[];
  subscriptionId?: string;
  payee: string;
  prefix: string;
  t: (key: string, params?: any) => string;
}) {
  if (!['subscription', 'setup'].includes(mode)) return null;

  if (subscriptions.length > 1) {
    return (
      <Box
        sx={{
          width: '100%',
          maxWidth: 420,
          borderRadius: 3,
          bgcolor: (theme) => (theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.04)' : 'grey.50'),
          border: '1px solid',
          borderColor: 'divider',
          overflow: 'hidden',
          animation: `${fadeUp} 0.5s ease 0.35s both`,
        }}>
        {subscriptions.map((sub: any, idx: number) => (
          <Box key={sub.id}>
            {idx > 0 && <Divider />}
            <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ px: 2.5, py: 1.5 }}>
              <Typography sx={{ fontSize: 13, fontWeight: 500, color: 'text.secondary', flex: 1, minWidth: 0 }} noWrap>
                {sub.description || sub.id}
              </Typography>
              <Box
                sx={{
                  flex: 1,
                  borderBottom: '1px dashed',
                  borderColor: 'grey.300',
                  mx: 2,
                  minWidth: 20,
                }}
              />
              <Link
                href={joinURL(prefix, `/customer/subscription/${sub.id}`)}
                underline="none"
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  gap: 0.5,
                  fontSize: 13,
                  fontWeight: 600,
                  color: 'primary.main',
                  flexShrink: 0,
                }}>
                {t('payment.checkout.next.view')}
                <OpenInNewIcon sx={{ fontSize: 14 }} />
              </Link>
            </Stack>
          </Box>
        ))}
      </Box>
    );
  }

  if (subscriptionId) {
    return (
      <Button
        variant="contained"
        href={joinURL(prefix, `/customer/subscription/${subscriptionId}`)}
        endIcon={<OpenInNewIcon sx={{ fontSize: 16 }} />}
        sx={{
          width: '100%',
          maxWidth: 320,
          height: 52,
          borderRadius: '16px',
          textTransform: 'none',
          fontWeight: 700,
          fontSize: { xs: 16, md: 17 },
          letterSpacing: '0.02em',
          color: (theme) => primaryContrastColor(theme),
          boxShadow: '0 8px 24px -4px rgba(59,130,246,0.25)',
          '&:hover': {
            boxShadow: '0 12px 28px -4px rgba(59,130,246,0.35)',
          },
          animation: `${fadeUp} 0.5s ease 0.35s both`,
        }}>
        {t('payment.checkout.next.subscription', { payee })}
      </Button>
    );
  }

  return null;
}

// ── Invoice Link ──

function InvoiceLink({
  mode,
  invoiceId = undefined,
  prefix,
  t,
}: {
  mode: string;
  invoiceId?: string;
  prefix: string;
  t: (key: string, params?: any) => string;
}) {
  if (mode !== 'payment' || !invoiceId) return null;

  return (
    <Button
      variant="contained"
      href={joinURL(prefix, `/customer/invoice/${invoiceId}`)}
      endIcon={<OpenInNewIcon sx={{ fontSize: 16 }} />}
      sx={{
        width: '100%',
        maxWidth: 320,
        height: 52,
        borderRadius: '16px',
        textTransform: 'none',
        fontWeight: 700,
        fontSize: { xs: 16, md: 17 },
        letterSpacing: '0.02em',
        color: (theme) => primaryContrastColor(theme),
        boxShadow: '0 8px 24px -4px rgba(59,130,246,0.25)',
        '&:hover': {
          boxShadow: '0 12px 28px -4px rgba(59,130,246,0.35)',
        },
        animation: `${fadeUp} 0.5s ease 0.35s both`,
      }}>
      {t('payment.checkout.next.invoice')}
    </Button>
  );
}

// ── Main Component ──

export default function SuccessView({ submit, session }: SuccessViewProps) {
  const { t, locale } = useLocaleContext();
  const { vendorStatus } = submit;
  const payee = getPayee(session);
  const prefix = getPrefix();

  const mode = session?.mode || 'payment';
  const resultSession = submit.result?.checkoutSession as any;
  const subscriptions = (session as any)?.subscriptions || [];
  const subscriptionId = (session as any)?.subscription_id || resultSession?.subscription_id;
  const invoiceId =
    (session as any)?.invoice_id ||
    (submit.result?.checkoutSession as any)?.invoice_id ||
    (submit.result?.checkoutSession as any)?.payment_intent?.invoice_id;
  const pageInfo = (session as any)?.metadata?.page_info;

  const customMessage = getCustomMessage(session);
  const submitType = (session as any)?.submit_type;
  const messageKey =
    submitType === 'donate' ? 'payment.checkout.completed.donate' : `payment.checkout.completed.${mode}`;
  const headline = customMessage || t(messageKey);

  const isVendorProcessing = vendorStatus && !vendorStatus.isAllCompleted && !vendorStatus.hasFailed;

  // Confetti
  const containerRef = useRef<HTMLDivElement>(null);
  const showConfetti = !vendorStatus?.hasFailed;
  useConfetti(containerRef, showConfetti);

  return (
    <Box
      ref={containerRef}
      sx={{
        position: 'relative',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        flex: 1,
        minHeight: 400,
        p: { xs: 3, md: 4 },
        textAlign: 'center',
        overflow: 'hidden',
      }}>
      <Stack spacing={3} alignItems="center" sx={{ width: '100%', maxWidth: 440 }}>
        {/* Hero icon */}
        {vendorStatus?.hasFailed ? (
          <ErrorOutlineIcon
            sx={{
              fontSize: 64,
              color: 'warning.main',
              animation: `${scaleIn} 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both`,
            }}
          />
        ) : (
          <HeroSuccessIcon />
        )}

        {/* Title + subtitle */}
        <Stack spacing={1} alignItems="center" sx={{ animation: `${fadeUp} 0.5s ease 0.2s both` }}>
          <Typography
            sx={{
              fontSize: { xs: 28, md: 36 },
              fontWeight: 800,
              color: 'text.primary',
              lineHeight: 1.2,
              letterSpacing: '-0.02em',
            }}>
            {headline}
          </Typography>
          {payee && (
            <Typography
              sx={{
                fontSize: { xs: 14, md: 16 },
                color: 'text.secondary',
                fontWeight: 500,
                lineHeight: 1.6,
                maxWidth: 360,
              }}>
              {t('payment.checkout.completed.tip', { payee })}
            </Typography>
          )}
        </Stack>

        {/* Payment receipt — trial/subscription summary */}
        <PaymentReceipt session={resultSession || session} t={t} />

        {/* Vendor progress panel */}
        {vendorStatus && <VendorProgressPanel vendorStatus={vendorStatus} pageInfo={pageInfo} locale={locale} t={t} />}

        {/* Vendor failed warning */}
        {vendorStatus?.hasFailed && vendorStatus.error && (
          <Alert severity="warning" sx={{ maxWidth: 420, borderRadius: 3, width: '100%' }}>
            {vendorStatus.error}
          </Alert>
        )}

        {/* Subscription links */}
        {!isVendorProcessing && (
          <SubscriptionLinks
            mode={mode}
            subscriptions={subscriptions}
            subscriptionId={subscriptionId}
            payee={payee}
            prefix={prefix}
            t={t}
          />
        )}

        {/* Invoice link */}
        {!isVendorProcessing && <InvoiceLink mode={mode} invoiceId={invoiceId} prefix={prefix} t={t} />}

        {/* Back button */}
        {!isVendorProcessing && (
          <Button
            variant="text"
            startIcon={<ArrowBackIcon sx={{ fontSize: 16 }} />}
            onClick={() => {
              if (window.history.length > 1) {
                window.history.back();
              } else {
                window.location.href = '/';
              }
            }}
            sx={{
              textTransform: 'none',
              fontWeight: 600,
              fontSize: 14,
              color: 'text.secondary',
              '&:hover': { bgcolor: 'action.hover' },
              animation: `${fadeUp} 0.5s ease 0.45s both`,
            }}>
            {t('common.back')}
          </Button>
        )}
      </Stack>
    </Box>
  );
}
