import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Package, Receipt, RefreshCcw, Sparkles } from 'lucide-react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
import toast from 'react-hot-toast';
import { MobileShell, HeaderActionButton } from './components/MobileShell';
import { MobileCard, CTAButton, PillBadge } from './components/Primitives';
import {
  createTenantBillingPortalSession,
  getTenantPackagesOverview,
  getTenantPaddleTransactions,
  TenantPackageSummary,
  PaddleTransactionSummary,
} from '../api';
import { TenantAddonHistoryEntry, getTenantAddonHistory } from '../api';
import { getApiErrorMessage } from '../lib/apiError';
import { ADMIN_EVENT_VIEW_PATH, adminPath } from '../constants';
import { buildPackageUsageMetrics, getUsageState, PackageUsageMetric, usagePercent } from './billingUsage';
import { useBackNavigation } from './hooks/useBackNavigation';
import { useAdminTheme } from './theme';
import {
  collectPackageFeatures,
  formatEventUsage,
  getPackageFeatureLabel,
  getPackageLimitEntries,
} from './lib/packageSummary';

export default function MobileBillingPage() {
  const { t } = useTranslation('management');
  const navigate = useNavigate();
  const location = useLocation();
  const { textStrong, text, muted, subtle, danger, border, primary, accentSoft } = useAdminTheme();
  const [packages, setPackages] = React.useState<TenantPackageSummary[]>([]);
  const [activePackage, setActivePackage] = React.useState<TenantPackageSummary | null>(null);
  const [transactions, setTransactions] = React.useState<PaddleTransactionSummary[]>([]);
  const [addons, setAddons] = React.useState<TenantAddonHistoryEntry[]>([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [portalBusy, setPortalBusy] = React.useState(false);
  const packagesRef = React.useRef<HTMLDivElement | null>(null);
  const invoicesRef = React.useRef<HTMLDivElement | null>(null);
  const supportEmail = 'support@fotospiel.de';
  const back = useBackNavigation(adminPath('/mobile/profile'));

  const load = React.useCallback(async () => {
    setLoading(true);
    try {
      const [pkg, trx, addonHistory] = await Promise.all([
        getTenantPackagesOverview({ force: true }),
        getTenantPaddleTransactions().catch(() => ({ data: [] as PaddleTransactionSummary[] })),
        getTenantAddonHistory().catch(() => ({ data: [] as TenantAddonHistoryEntry[] })),
      ]);
      setPackages(pkg.packages ?? []);
      setActivePackage(pkg.activePackage ?? null);
      setTransactions(trx.data ?? []);
      setAddons(addonHistory.data ?? []);
      setError(null);
    } catch (err) {
      const message = getApiErrorMessage(err, t('billing.errors.load', 'Konnte Abrechnung nicht laden.'));
      setError(message);
    } finally {
      setLoading(false);
    }
  }, [t]);

  const scrollToPackages = React.useCallback(() => {
    packagesRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }, []);

  const openSupport = React.useCallback(() => {
    if (typeof window !== 'undefined') {
      window.location.href = `mailto:${supportEmail}`;
    }
  }, [supportEmail]);

  const openPortal = React.useCallback(async () => {
    if (portalBusy) {
      return;
    }

    setPortalBusy(true);
    try {
      const { url } = await createTenantBillingPortalSession();
      if (typeof window !== 'undefined') {
        window.open(url, '_blank', 'noopener');
      }
    } catch (err) {
      const message = getApiErrorMessage(err, t('billing.errors.portal', 'Konnte das Paddle-Portal nicht öffnen.'));
      toast.error(message);
    } finally {
      setPortalBusy(false);
    }
  }, [portalBusy, t]);

  React.useEffect(() => {
    void load();
  }, [load]);

  React.useEffect(() => {
    if (!location.hash) return;
    const hash = location.hash.replace('#', '');
    const target = hash === 'invoices' ? invoicesRef.current : packagesRef.current;
    if (target) {
      target.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  }, [location.hash, loading]);

  React.useEffect(() => {
    if (!location.search) {
      return;
    }

    const params = new URLSearchParams(location.search);
    const checkout = params.get('checkout');
    if (!checkout) {
      return;
    }

    if (checkout === 'success') {
      toast.success(t('billing.checkoutSuccess', 'Checkout completed. Your package will activate shortly.'));
    } else if (checkout === 'cancel') {
      toast(t('billing.checkoutCancelled', 'Checkout was cancelled.'));
    }

    params.delete('checkout');
    navigate(
      {
        pathname: location.pathname,
        search: params.toString(),
        hash: location.hash,
      },
      { replace: true },
    );
  }, [location.hash, location.pathname, location.search, navigate, t]);

  return (
    <MobileShell
      activeTab="profile"
      title={t('billing.title', 'Billing & Packages')}
      onBack={back}
      headerActions={
        <HeaderActionButton onPress={() => load()} ariaLabel={t('common.refresh', 'Refresh')}>
          <RefreshCcw size={18} color={textStrong} />
        </HeaderActionButton>
      }
    >
      {error ? (
        <MobileCard>
          <Text fontWeight="700" color={danger}>
            {error}
          </Text>
          <CTAButton label={t('billing.actions.refresh', 'Refresh')} tone="ghost" onPress={load} />
        </MobileCard>
      ) : null}

      <MobileCard space="$2" ref={packagesRef as any}>
        <XStack alignItems="center" space="$2">
          <Package size={18} color={textStrong} />
          <Text fontSize="$md" fontWeight="800" color={textStrong}>
            {t('billing.sections.packages.title', 'Packages')}
          </Text>
        </XStack>
        <Text fontSize="$xs" color={muted}>
          {t('billing.sections.packages.hint', 'Active package, limits, and history at a glance.')}
        </Text>
        <CTAButton
          label={portalBusy ? t('billing.actions.portalBusy', 'Öffne Portal...') : t('billing.actions.portal', 'Manage in Paddle')}
          onPress={openPortal}
          disabled={portalBusy}
        />
        {loading ? (
          <Text fontSize="$sm" color={muted}>
            {t('common.loading', 'Lädt...')}
          </Text>
        ) : (
          <YStack space="$2">
            {activePackage ? (
              <PackageCard
                pkg={activePackage}
                label={t('billing.sections.packages.card.statusActive', 'Aktiv')}
                isActive
                onOpenPortal={openPortal}
                portalBusy={portalBusy}
              />
            ) : null}
            {packages
              .filter((pkg) => !activePackage || pkg.id !== activePackage.id)
              .map((pkg) => (
                <PackageCard key={pkg.id} pkg={pkg} />
              ))}
          </YStack>
        )}
      </MobileCard>

      <MobileCard space="$2" ref={invoicesRef as any}>
        <XStack alignItems="center" space="$2">
          <Receipt size={18} color={textStrong} />
          <Text fontSize="$md" fontWeight="800" color={textStrong}>
            {t('billing.sections.invoices.title', 'Invoices & Payments')}
          </Text>
        </XStack>
        <Text fontSize="$xs" color={muted}>
          {t('billing.sections.invoices.hint', 'Review transactions and download receipts.')}
        </Text>
        {loading ? (
          <Text fontSize="$sm" color={muted}>
            {t('common.loading', 'Lädt...')}
          </Text>
        ) : transactions.length === 0 ? (
          <YStack space="$2">
            <Text fontSize="$sm" color={text}>
              {t('billing.sections.invoices.empty', 'Keine Zahlungen gefunden.')}
            </Text>
            <CTAButton label={t('billing.actions.openPackages', 'Open packages')} onPress={scrollToPackages} />
            <CTAButton label={t('billing.actions.contactSupport', 'Contact support')} tone="ghost" onPress={openSupport} />
          </YStack>
        ) : (
          <YStack space="$1.5">
            {transactions.slice(0, 8).map((trx) => (
              <XStack key={trx.id} alignItems="center" justifyContent="space-between" borderBottomWidth={1} borderColor={border} paddingVertical="$1.5">
                <YStack>
                  <Text fontSize="$sm" color={textStrong} fontWeight="700">
                    {trx.status ?? '—'}
                  </Text>
                  <Text fontSize="$xs" color={muted}>
                    {formatDate(trx.created_at)}
                  </Text>
                  {trx.origin ? (
                    <Text fontSize="$xs" color={subtle}>
                      {trx.origin}
                    </Text>
                  ) : null}
                </YStack>
                <YStack alignItems="flex-end">
                  <Text fontSize="$sm" color={textStrong} fontWeight="700">
                    {formatAmount(trx.amount, trx.currency)}
                  </Text>
                  {trx.tax ? (
                    <Text fontSize="$xs" color={muted}>
                      {t('billing.sections.transactions.labels.tax', { value: formatAmount(trx.tax, trx.currency) })}
                    </Text>
                  ) : null}
                  {trx.receipt_url ? (
                    <a href={trx.receipt_url} target="_blank" rel="noreferrer" style={{ fontSize: 12, color: primary }}>
                      {t('billing.sections.transactions.labels.receipt', 'Beleg')}
                    </a>
                  ) : null}
                </YStack>
              </XStack>
            ))}
          </YStack>
        )}
      </MobileCard>

      <MobileCard space="$2">
        <XStack alignItems="center" space="$2">
          <Sparkles size={18} color={textStrong} />
          <Text fontSize="$md" fontWeight="800" color={textStrong}>
            {t('billing.sections.addOns.title', 'Add-ons')}
          </Text>
        </XStack>
        <Text fontSize="$xs" color={muted}>
          {t('billing.sections.addOns.hint', 'Track extra photo, guest, or time bundles per event.')}
        </Text>
        {loading ? (
          <Text fontSize="$sm" color={muted}>
            {t('common.loading', 'Lädt...')}
          </Text>
        ) : addons.length === 0 ? (
          <Text fontSize="$sm" color={text}>
            {t('billing.sections.addOns.empty', 'Keine Add-ons gebucht.')}
          </Text>
        ) : (
          <YStack space="$1.5">
            {addons.slice(0, 8).map((addon) => (
              <AddonRow key={addon.id} addon={addon} />
            ))}
          </YStack>
        )}
      </MobileCard>
    </MobileShell>
  );
}

function PackageCard({
  pkg,
  label,
  isActive = false,
  onOpenPortal,
  portalBusy,
}: {
  pkg: TenantPackageSummary;
  label?: string;
  isActive?: boolean;
  onOpenPortal?: () => void;
  portalBusy?: boolean;
}) {
  const { t } = useTranslation('management');
  const { border, primary, accentSoft, textStrong, muted } = useAdminTheme();
  const limits = (pkg.package_limits ?? null) as Record<string, unknown> | null;
  const limitMaxEvents = typeof limits?.max_events_per_year === 'number' ? (limits?.max_events_per_year as number) : null;
  const remaining = pkg.remaining_events ?? limitMaxEvents ?? 0;
  const remainingText =
    remaining === 0
      ? t('mobileBilling.remainingEventsZero', 'No events remaining')
      : limitMaxEvents
        ? t('mobileBilling.remainingEventsOf', '{{remaining}} of {{limit}} events remaining', {
          remaining,
          limit: limitMaxEvents,
        })
        : t('mobileBilling.remainingEvents', '{{count}} events', { count: remaining });
  const expires = pkg.expires_at ? formatDate(pkg.expires_at) : null;
  const usageMetrics = buildPackageUsageMetrics(pkg);
  const usageStates = usageMetrics.map((metric) => getUsageState(metric));
  const hasUsageWarning = usageStates.some((state) => state === 'warning' || state === 'danger');
  const isDanger = usageStates.includes('danger');
  const limitEntries = getPackageLimitEntries(limits, t, {
    remainingEvents: pkg.remaining_events ?? null,
    usedEvents: typeof pkg.used_events === 'number' ? pkg.used_events : null,
  });
  const featureKeys = collectPackageFeatures(pkg);
  const eventUsageText = formatEventUsage(
    typeof pkg.used_events === 'number' ? pkg.used_events : null,
    limitMaxEvents,
    t
  );
  return (
    <MobileCard
      borderColor={isActive ? primary : border}
      borderWidth={isActive ? 2 : 1}
      backgroundColor={isActive ? accentSoft : undefined}
      space="$2"
    >
      <XStack alignItems="center" justifyContent="space-between">
        <Text fontSize="$md" fontWeight="800" color={textStrong}>
          {pkg.package_name ?? t('mobileBilling.packageFallback', 'Package')}
        </Text>
        {label ? <PillBadge tone="success">{label}</PillBadge> : null}
      </XStack>
      {expires ? (
        <Text fontSize="$xs" color={muted}>
          {expires}
        </Text>
      ) : null}
      <XStack space="$2" marginTop="$2" flexWrap="wrap">
        <PillBadge tone="muted">{remainingText}</PillBadge>
        {pkg.price !== null && pkg.price !== undefined ? (
          <PillBadge tone="muted">{formatAmount(pkg.price, pkg.currency ?? 'EUR')}</PillBadge>
        ) : null}
        {renderFeatureBadge(pkg, t, 'branding_allowed', t('billing.features.branding', 'Branding'))}
        {renderFeatureBadge(pkg, t, 'watermark_allowed', t('billing.features.watermark', 'Watermark'))}
      </XStack>
      {eventUsageText ? (
        <Text fontSize="$xs" color={muted}>
          {eventUsageText}
        </Text>
      ) : null}
      {limitEntries.length ? (
        <YStack space="$1.5" marginTop="$2">
          <Text fontSize="$xs" color={muted}>
            {t('mobileBilling.details.limitsTitle', 'Limits')}
          </Text>
          {limitEntries.map((entry) => (
            <XStack key={entry.key} alignItems="center" justifyContent="space-between">
              <Text fontSize="$xs" color={muted}>
                {entry.label}
              </Text>
              <Text fontSize="$xs" color={textStrong} fontWeight="700">
                {entry.value}
              </Text>
            </XStack>
          ))}
        </YStack>
      ) : null}
      {featureKeys.length ? (
        <YStack space="$1.5" marginTop="$2">
          <Text fontSize="$xs" color={muted}>
            {t('mobileBilling.details.featuresTitle', 'Features')}
          </Text>
          {featureKeys.map((feature) => (
            <XStack key={feature} alignItems="center" space="$2">
              <Sparkles size={14} color={primary} />
              <Text fontSize="$xs" color={textStrong}>
                {getPackageFeatureLabel(feature, t)}
              </Text>
            </XStack>
          ))}
        </YStack>
      ) : null}
      {usageMetrics.length ? (
        <YStack space="$2" marginTop="$2">
          {usageMetrics.map((metric) => (
            <UsageBar key={metric.key} metric={metric} />
          ))}
        </YStack>
      ) : null}
      {isActive && hasUsageWarning && onOpenPortal ? (
        <CTAButton
          label={
            isDanger
              ? t('mobileBilling.usage.ctaDanger', 'Upgrade package')
              : t('mobileBilling.usage.ctaWarning', 'Secure more capacity')
          }
          onPress={onOpenPortal}
          disabled={portalBusy}
          tone={isDanger ? 'danger' : 'primary'}
        />
      ) : null}
    </MobileCard>
  );
}

function renderFeatureBadge(pkg: TenantPackageSummary, t: any, key: string, label: string) {
  const value = (pkg.package_limits as any)?.[key] ?? (pkg as any)[key];
  if (value === undefined || value === null) return null;
  const enabled = value !== false;
  return <PillBadge tone={enabled ? 'success' : 'muted'}>{enabled ? label : `${label} off`}</PillBadge>;
}

function UsageBar({ metric }: { metric: PackageUsageMetric }) {
  const { t } = useTranslation('management');
  const { muted, textStrong, border, primary, subtle, warningText, danger } = useAdminTheme();
  const labelMap: Record<PackageUsageMetric['key'], string> = {
    events: t('mobileBilling.usage.events', 'Events'),
    guests: t('mobileBilling.usage.guests', 'Guests'),
    photos: t('mobileBilling.usage.photos', 'Photos'),
    gallery: t('mobileBilling.usage.gallery', 'Gallery days'),
  };

  if (!metric.limit) {
    return null;
  }

  const status = getUsageState(metric);
  const hasUsage = metric.used !== null;
  const valueText = hasUsage
    ? t('mobileBilling.usage.value', { used: metric.used, limit: metric.limit })
    : t('mobileBilling.usage.limit', { limit: metric.limit });
  const remainingText = metric.remaining !== null
    ? t('mobileBilling.usage.remainingOf', {
      remaining: metric.remaining,
      limit: metric.limit,
      defaultValue: 'Remaining {{remaining}} of {{limit}}',
    })
    : null;
  const fill = usagePercent(metric);
  const statusLabel =
    status === 'danger'
      ? t('mobileBilling.usage.statusDanger', 'Limit reached')
      : status === 'warning'
        ? t('mobileBilling.usage.statusWarning', 'Low')
        : null;
  const fillColor = status === 'danger' ? danger : status === 'warning' ? warningText : primary;

  return (
    <YStack space="$1.5">
      <XStack alignItems="center" justifyContent="space-between">
        <Text fontSize="$xs" color={muted}>
          {labelMap[metric.key]}
        </Text>
        <XStack alignItems="center" space="$1.5">
          {statusLabel ? <PillBadge tone={status === 'danger' ? 'danger' : 'warning'}>{statusLabel}</PillBadge> : null}
          <Text fontSize="$xs" color={textStrong} fontWeight="700">
            {valueText}
          </Text>
        </XStack>
      </XStack>
      <YStack height={6} borderRadius={999} backgroundColor={border} overflow="hidden">
        <YStack height="100%" width={`${fill}%`} backgroundColor={hasUsage ? fillColor : subtle} />
      </YStack>
      {remainingText ? (
        <Text fontSize="$xs" color={muted}>
          {remainingText}
        </Text>
      ) : null}
    </YStack>
  );
}

function formatAmount(value: number | null | undefined, currency: string | null | undefined): string {
  if (value === null || value === undefined) {
    return '—';
  }
  const cur = currency ?? 'EUR';
  try {
    return new Intl.NumberFormat(undefined, { style: 'currency', currency: cur }).format(value);
  } catch {
    return `${value} ${cur}`;
  }
}

function AddonRow({ addon }: { addon: TenantAddonHistoryEntry }) {
  const { t } = useTranslation('management');
  const navigate = useNavigate();
  const { border, textStrong, text, muted, subtle, primary } = useAdminTheme();
  const labels: Record<TenantAddonHistoryEntry['status'], { tone: 'success' | 'warning' | 'muted'; text: string }> = {
    completed: { tone: 'success', text: t('mobileBilling.status.completed', 'Completed') },
    pending: { tone: 'warning', text: t('mobileBilling.status.pending', 'Pending') },
    failed: { tone: 'muted', text: t('mobileBilling.status.failed', 'Failed') },
  };
  const status = labels[addon.status];
  const eventName =
    (addon.event?.name && typeof addon.event.name === 'string' && addon.event.name) ||
    (addon.event?.name && typeof addon.event.name === 'object' ? addon.event.name?.en ?? addon.event.name?.de ?? Object.values(addon.event.name)[0] : null) ||
    null;
  const eventPath = addon.event?.slug ? ADMIN_EVENT_VIEW_PATH(addon.event.slug) : null;
  const hasImpact = Boolean(addon.extra_photos || addon.extra_guests || addon.extra_gallery_days);
  const impactBadges = hasImpact ? (
    <XStack space="$2" marginTop="$1.5" flexWrap="wrap">
      {addon.extra_photos ? (
        <PillBadge tone="muted">{t('mobileBilling.extra.photos', '+{{count}} photos', { count: addon.extra_photos })}</PillBadge>
      ) : null}
      {addon.extra_guests ? (
        <PillBadge tone="muted">{t('mobileBilling.extra.guests', '+{{count}} guests', { count: addon.extra_guests })}</PillBadge>
      ) : null}
      {addon.extra_gallery_days ? (
        <PillBadge tone="muted">{t('mobileBilling.extra.days', '+{{count}} days', { count: addon.extra_gallery_days })}</PillBadge>
      ) : null}
    </XStack>
  ) : null;

  return (
    <MobileCard borderColor={border} padding="$3" space="$1.5">
      <XStack alignItems="center" justifyContent="space-between">
        <Text fontSize="$sm" fontWeight="700" color={textStrong}>
          {addon.label ?? addon.addon_key}
        </Text>
        <PillBadge tone={status.tone}>{status.text}</PillBadge>
      </XStack>
      {eventName ? (
        eventPath ? (
          <Pressable onPress={() => navigate(eventPath)}>
            <XStack alignItems="center" justifyContent="space-between">
              <Text fontSize="$xs" color={textStrong} fontWeight="600">
                {eventName}
              </Text>
              <Text fontSize="$xs" color={primary} fontWeight="700">
                {t('mobileBilling.openEvent', 'Open event')}
              </Text>
            </XStack>
          </Pressable>
        ) : (
          <Text fontSize="$xs" color={subtle}>
            {eventName}
          </Text>
        )
      ) : null}
      {impactBadges}
      <Text fontSize="$sm" color={text} marginTop="$1.5">
        {formatAmount(addon.amount, addon.currency)}
      </Text>
      <Text fontSize="$xs" color={muted}>
        {formatDate(addon.purchased_at)}
      </Text>
    </MobileCard>
  );
}
function formatDate(value: string | null | undefined): string {
  if (!value) return '—';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '—';
  return date.toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' });
}
