import React from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Image as ImageIcon, Sparkles, Users, Clock3, Layers } from 'lucide-react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import toast from 'react-hot-toast';

import {
  createEventAddonCheckout,
  EventAddonCatalogItem,
  getAddonCatalog,
  getEvent,
  getTenantAddonHistory,
  TenantAddonHistoryEntry,
  TenantEvent,
} from '../api';
import { getApiErrorMessage } from '../lib/apiError';
import { buildLimitWarnings } from '../lib/limitWarnings';
import { adminPath, ADMIN_EVENT_ADDON_SUCCESS_PATH, ADMIN_EVENT_VIEW_PATH } from '../constants';
import { useBackNavigation } from './hooks/useBackNavigation';
import { useAdminTheme } from './theme';
import { MobileShell } from './components/MobileShell';
import { CTAButton, MobileCard, PillBadge, SkeletonCard } from './components/Primitives';
import { LegalConsentSheet } from './components/LegalConsentSheet';
import { scopeDefaults, selectAddonKeyForScope } from './addons';

type AddonScope = 'photos' | 'guests' | 'gallery' | 'bundle' | 'feature';

type ScopedAddon = EventAddonCatalogItem & {
  scope: AddonScope;
  price: number | null;
  currency: string;
};

function translateLimits(t: any) {
  return (key: string, options?: Record<string, unknown>) => t(`limits.${key}`, key, options);
}

function resolveAddonScope(addon: EventAddonCatalogItem): AddonScope {
  const increments = addon.increments ?? {};
  const photos = Number(increments.extra_photos ?? 0);
  const guests = Number(increments.extra_guests ?? 0);
  const gallery = Number(increments.extra_gallery_days ?? 0);

  const count = Number(photos > 0) + Number(guests > 0) + Number(gallery > 0);

  if (count === 0 || addon.key.includes('ai')) {
    return 'feature';
  }

  if (count > 1 || addon.key.includes('boost') || addon.key.includes('bundle')) {
    return 'bundle';
  }

  if (photos > 0) {
    return 'photos';
  }

  if (guests > 0) {
    return 'guests';
  }

  return 'gallery';
}

function normalizeAddon(addon: EventAddonCatalogItem): ScopedAddon {
  const payload = addon as EventAddonCatalogItem & { price?: number | null; currency?: string | null };

  return {
    ...addon,
    scope: resolveAddonScope(addon),
    price: typeof payload.price === 'number' && Number.isFinite(payload.price) ? payload.price : null,
    currency: typeof payload.currency === 'string' && payload.currency ? payload.currency : 'EUR',
  };
}

function formatAmount(value: number | null, currency: string): string {
  if (value === null) {
    return '—';
  }

  try {
    return new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(value);
  } catch {
    return `${value} ${currency}`;
  }
}

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' });
}

function scopeIcon(scope: AddonScope) {
  if (scope === 'photos') {
    return ImageIcon;
  }

  if (scope === 'guests') {
    return Users;
  }

  if (scope === 'gallery') {
    return Clock3;
  }

  return scope === 'bundle' ? Layers : Sparkles;
}

function scopeLabel(scope: AddonScope, t: (key: string, fallback: string) => string): string {
  if (scope === 'photos') {
    return t('events.addons.groups.photos', 'Photo capacity');
  }

  if (scope === 'guests') {
    return t('events.addons.groups.guests', 'Guest capacity');
  }

  if (scope === 'gallery') {
    return t('events.addons.groups.gallery', 'Gallery runtime');
  }

  if (scope === 'bundle') {
    return t('events.addons.groups.bundle', 'Bundles');
  }

  return t('events.addons.groups.feature', 'Feature unlocks');
}

function resolveScopeFromQuery(input: string | null): 'photos' | 'guests' | 'gallery' | 'ai' | null {
  if (!input) {
    return null;
  }

  if (input === 'photos' || input === 'guests' || input === 'gallery' || input === 'ai') {
    return input;
  }

  return null;
}

function resolveEventName(
  name: TenantEvent['name'],
  t: (key: string, fallback: string) => string,
): string {
  if (typeof name === 'string' && name.trim() !== '') {
    return name;
  }

  if (name && typeof name === 'object') {
    return name.de ?? name.en ?? Object.values(name)[0] ?? t('events.placeholders.untitled', 'Untitled event');
  }

  return t('events.placeholders.untitled', 'Untitled event');
}

export default function MobileEventAddonsPage() {
  const { slug } = useParams<{ slug: string }>();
  const navigate = useNavigate();
  const location = useLocation();
  const { t } = useTranslation('management');
  const { textStrong, text, muted, border, primary, danger } = useAdminTheme();
  const back = useBackNavigation(slug ? ADMIN_EVENT_VIEW_PATH(slug) : adminPath('/mobile/events'));

  const [event, setEvent] = React.useState<TenantEvent | null>(null);
  const [catalog, setCatalog] = React.useState<ScopedAddon[]>([]);
  const [history, setHistory] = React.useState<TenantAddonHistoryEntry[]>([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [consentOpen, setConsentOpen] = React.useState(false);
  const [checkoutBusy, setCheckoutBusy] = React.useState(false);
  const [pendingAddonKey, setPendingAddonKey] = React.useState<string | null>(null);

  const queryScope = React.useMemo(() => {
    const params = new URLSearchParams(location.search);
    return resolveScopeFromQuery(params.get('scope'));
  }, [location.search]);
  const queryAddonKey = React.useMemo(() => {
    const params = new URLSearchParams(location.search);
    return params.get('addon');
  }, [location.search]);

  const load = React.useCallback(async () => {
    if (!slug) {
      return;
    }

    setLoading(true);

    try {
      const [eventData, catalogData] = await Promise.all([
        getEvent(slug),
        getAddonCatalog(),
      ]);

      setEvent(eventData);
      setCatalog(catalogData.map(normalizeAddon));

      const historyResult = await getTenantAddonHistory({
        eventId: eventData.id,
        perPage: 20,
        page: 1,
      }).catch(() => ({ data: [] as TenantAddonHistoryEntry[] }));
      setHistory(historyResult.data ?? []);
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, 'Add-ons konnten nicht geladen werden.'));
    } finally {
      setLoading(false);
    }
  }, [slug]);

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

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

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

    toast.success(t('mobileBilling.addonApplied', 'Add-on applied. Limits update shortly.'));
    params.delete('addon_success');

    navigate(
      {
        pathname: adminPath(`/mobile/events/${slug}/addons`),
        search: params.toString(),
      },
      { replace: true },
    );

    void load();
  }, [load, location.search, navigate, slug, t]);

  const warnings = React.useMemo(() => buildLimitWarnings(event?.limits ?? null, translateLimits(t as any)), [event?.limits, t]);

  const suggestedKeys = React.useMemo(() => {
    const keys = new Set<string>();

    if (queryAddonKey) {
      keys.add(queryAddonKey);
    }

    if (queryScope === 'photos' || queryScope === 'guests' || queryScope === 'gallery') {
      keys.add(selectAddonKeyForScope(catalog, queryScope));
    }

    if (queryScope === 'ai') {
      const aiAddon = catalog.find((addon) => addon.scope === 'feature' && addon.key.includes('ai'));
      if (aiAddon) {
        keys.add(aiAddon.key);
      }
    }

    for (const warning of warnings) {
      if (warning.scope === 'photos' || warning.scope === 'guests' || warning.scope === 'gallery') {
        keys.add(selectAddonKeyForScope(catalog, warning.scope));
      }
    }

    return keys;
  }, [catalog, queryAddonKey, queryScope, warnings]);

  const grouped = React.useMemo(() => {
    const scopes: AddonScope[] = ['photos', 'guests', 'gallery', 'bundle', 'feature'];
    return scopes.map((scope) => {
      const addons = catalog
        .filter((addon) => addon.scope === scope)
        .sort((left, right) => (left.price ?? Number.MAX_SAFE_INTEGER) - (right.price ?? Number.MAX_SAFE_INTEGER));

      return { scope, addons };
    });
  }, [catalog]);

  const recommendedAddons = React.useMemo(
    () => catalog.filter((addon) => suggestedKeys.has(addon.key)),
    [catalog, suggestedKeys],
  );

  const hasSellableAddons = catalog.some((addon) => Boolean(addon.price_id));

  function openConsent(addonKey: string) {
    if (!slug || checkoutBusy) {
      return;
    }

    setPendingAddonKey(addonKey);
    setConsentOpen(true);
  }

  async function confirmCheckout(consents: { acceptedTerms: boolean; acceptedWaiver: boolean }) {
    if (!slug || !pendingAddonKey) {
      return;
    }

    setCheckoutBusy(true);

    const pagePath = adminPath(`/mobile/events/${slug}/addons`);
    const currentUrl = `${window.location.origin}${pagePath}`;
    const successPath = `${ADMIN_EVENT_ADDON_SUCCESS_PATH(slug)}?addon_key=${encodeURIComponent(pendingAddonKey)}`;
    const successUrl = `${window.location.origin}${successPath}`;

    try {
      const checkout = await createEventAddonCheckout(slug, {
        addon_key: pendingAddonKey,
        success_url: successUrl,
        cancel_url: currentUrl,
        accepted_terms: consents.acceptedTerms,
        accepted_waiver: consents.acceptedWaiver,
      });

      if (checkout.checkout_url) {
        window.location.href = checkout.checkout_url;
        return;
      }

      toast.error(t('events.errors.checkoutMissing', 'Checkout could not be started.'));
    } catch (err) {
      toast.error(getApiErrorMessage(err, t('events.errors.checkoutFailed', 'Add-on checkout failed.')));
    } finally {
      setCheckoutBusy(false);
      setConsentOpen(false);
      setPendingAddonKey(null);
    }
  }

  if (loading) {
    return (
      <MobileShell title={t('events.addons.title', 'Event add-ons')} activeTab="home" onBack={back}>
        <YStack gap="$3">
          <SkeletonCard height={120} />
          <SkeletonCard height={220} />
          <SkeletonCard height={180} />
        </YStack>
      </MobileShell>
    );
  }

  if (error || !event) {
    return (
      <MobileShell title={t('events.addons.title', 'Event add-ons')} activeTab="home" onBack={back}>
        <MobileCard>
          <Text fontWeight="700" color={danger}>
            {error || t('common.error', 'Something went wrong.')}
          </Text>
          <CTAButton label={t('common.retry', 'Retry')} tone="ghost" onPress={load} />
        </MobileCard>
      </MobileShell>
    );
  }

  return (
    <MobileShell title={t('events.addons.title', 'Event add-ons')} activeTab="home" onBack={back}>
      <YStack gap="$3">
        <MobileCard gap="$2">
          <Text fontSize="$sm" color={muted}>
            {t('events.addons.event', 'Event')}
          </Text>
          <Text fontSize="$lg" fontWeight="800" color={textStrong}>
            {resolveEventName(event.name, t as any)}
          </Text>
          {event.package?.name ? (
            <XStack gap="$2" alignItems="center" flexWrap="wrap">
              <PillBadge tone="success">{event.package.name}</PillBadge>
              {event.package.expires_at ? (
                <PillBadge tone="muted">
                  {t('events.addons.packageExpires', 'Gallery active until {{date}}', {
                    date: formatDate(event.package.expires_at),
                  })}
                </PillBadge>
              ) : null}
            </XStack>
          ) : (
            <Text fontSize="$sm" color={muted}>
              {t('events.addons.noPackage', 'No package is currently assigned to this event.')}
            </Text>
          )}
        </MobileCard>

        {recommendedAddons.length > 0 ? (
          <MobileCard gap="$2" borderColor={primary}>
            <Text fontSize="$md" fontWeight="800" color={textStrong}>
              {t('events.addons.recommendedTitle', 'Recommended now')}
            </Text>
            <Text fontSize="$sm" color={text}>
              {t('events.addons.recommendedBody', 'Based on your event usage, these add-ons are likely most relevant.')}
            </Text>
            <YStack gap="$2">
              {recommendedAddons.map((addon) => (
                <AddonCard
                  key={`recommended-${addon.key}`}
                  addon={addon}
                  textStrong={textStrong}
                  muted={muted}
                  onBuy={openConsent}
                  busy={checkoutBusy && pendingAddonKey === addon.key}
                  isRecommended
                  t={t as any}
                />
              ))}
            </YStack>
          </MobileCard>
        ) : null}

        {!hasSellableAddons ? (
          <MobileCard>
            <Text fontSize="$sm" color={muted}>
              {t('events.addons.noAddonAvailable', 'No add-ons are currently available.')}
            </Text>
          </MobileCard>
        ) : (
          grouped.map((group) => {
            if (!group.addons.length) {
              return null;
            }

            const GroupIcon = scopeIcon(group.scope);

            return (
              <MobileCard key={group.scope} gap="$2">
                <XStack gap="$2" alignItems="center">
                  <GroupIcon size={16} color={primary} />
                  <Text fontSize="$md" fontWeight="800" color={textStrong}>
                    {scopeLabel(group.scope, t as any)}
                  </Text>
                </XStack>
                <YStack gap="$2">
                  {group.addons.map((addon) => (
                    <AddonCard
                      key={addon.key}
                      addon={addon}
                      textStrong={textStrong}
                      muted={muted}
                      onBuy={openConsent}
                      busy={checkoutBusy && pendingAddonKey === addon.key}
                      isRecommended={suggestedKeys.has(addon.key)}
                      t={t as any}
                    />
                  ))}
                </YStack>
              </MobileCard>
            );
          })
        )}

        <MobileCard gap="$2">
          <Text fontSize="$md" fontWeight="800" color={textStrong}>
            {t('events.addons.historyTitle', 'Purchased add-ons for this event')}
          </Text>
          {history.length === 0 ? (
            <Text fontSize="$sm" color={muted}>
              {t('billing.sections.currentEvent.noAddons', 'No add-ons purchased for this event.')}
            </Text>
          ) : (
            <YStack gap="$1.5">
              {history.map((entry) => (
                <XStack
                  key={entry.id}
                  alignItems="center"
                  justifyContent="space-between"
                  borderBottomWidth={1}
                  borderColor={border}
                  paddingBottom="$1.5"
                >
                  <YStack>
                    <Text fontSize="$sm" fontWeight="700" color={textStrong}>
                      {entry.label ?? entry.addon_key}
                    </Text>
                    <Text fontSize="$xs" color={muted}>
                      {formatDate(entry.purchased_at)}
                    </Text>
                  </YStack>
                  <YStack alignItems="flex-end" gap="$1">
                    <Text fontSize="$sm" color={textStrong}>
                      {formatAmount(entry.amount, entry.currency)}
                    </Text>
                    <PillBadge tone={entry.status === 'completed' ? 'success' : entry.status === 'pending' ? 'warning' : 'muted'}>
                      {t(`mobileBilling.status.${entry.status}`, entry.status)}
                    </PillBadge>
                  </YStack>
                </XStack>
              ))}
            </YStack>
          )}
        </MobileCard>
      </YStack>

      <LegalConsentSheet
        open={consentOpen}
        busy={checkoutBusy}
        onClose={() => {
          if (!checkoutBusy) {
            setConsentOpen(false);
            setPendingAddonKey(null);
          }
        }}
        onConfirm={confirmCheckout}
        t={t as any}
      />
    </MobileShell>
  );
}

function AddonCard({
  addon,
  textStrong,
  muted,
  onBuy,
  busy,
  isRecommended,
  t,
}: {
  addon: ScopedAddon;
  textStrong: string;
  muted: string;
  onBuy: (addonKey: string) => void;
  busy: boolean;
  isRecommended: boolean;
  t: (key: string, fallback: string, options?: Record<string, unknown>) => string;
}) {
  return (
    <MobileCard borderRadius={14} padding="$3" gap="$2" borderWidth={isRecommended ? 2 : 1}>
      <XStack alignItems="center" justifyContent="space-between" gap="$2">
        <YStack gap="$0.5" flex={1}>
          <Text fontSize="$sm" fontWeight="700" color={textStrong}>
            {addon.label || addon.key}
          </Text>
          <Text fontSize="$xs" color={muted}>
            {formatAmount(addon.price, addon.currency)}
          </Text>
        </YStack>
        {isRecommended ? <PillBadge tone="warning">{t('events.addons.recommendedBadge', 'Recommended')}</PillBadge> : null}
      </XStack>

      <XStack gap="$2" flexWrap="wrap">
        {Number(addon.increments?.extra_photos ?? 0) > 0 ? (
          <PillBadge tone="muted">
            {t('mobileBilling.extra.photos', '+{{count}} photos', { count: Number(addon.increments?.extra_photos ?? 0) })}
          </PillBadge>
        ) : null}
        {Number(addon.increments?.extra_guests ?? 0) > 0 ? (
          <PillBadge tone="muted">
            {t('mobileBilling.extra.guests', '+{{count}} guests', { count: Number(addon.increments?.extra_guests ?? 0) })}
          </PillBadge>
        ) : null}
        {Number(addon.increments?.extra_gallery_days ?? 0) > 0 ? (
          <PillBadge tone="muted">
            {t('mobileBilling.extra.days', '+{{count}} days', { count: Number(addon.increments?.extra_gallery_days ?? 0) })}
          </PillBadge>
        ) : null}
      </XStack>

      <CTAButton
        label={t('events.addons.buyAction', 'Buy add-on')}
        onPress={() => onBuy(addon.key)}
        loading={busy}
      />
    </MobileCard>
  );
}
