import React from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Image as ImageIcon, RefreshCcw, Search, Filter } 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 { MobileShell } from './components/MobileShell';
import { MobileCard, PillBadge, CTAButton } from './components/Primitives';
import {
  getEventPhotos,
  updatePhotoVisibility,
  featurePhoto,
  unfeaturePhoto,
  TenantPhoto,
  EventAddonCatalogItem,
  createEventAddonCheckout,
  getAddonCatalog,
  EventAddonSummary,
  EventLimitSummary,
  getEvent,
} from '../api';
import toast from 'react-hot-toast';
import { isAuthError } from '../auth/tokens';
import { getApiErrorMessage } from '../lib/apiError';
import { MobileSheet } from './components/Sheet';
import { useEventContext } from '../context/EventContext';
import { useTheme } from '@tamagui/core';
import { buildLimitWarnings } from '../lib/limitWarnings';
import { adminPath } from '../constants';
import { scopeDefaults, selectAddonKeyForScope } from './addons';

type FilterKey = 'all' | 'featured' | 'hidden';

export default function MobileEventPhotosPage() {
  const { slug: slugParam } = useParams<{ slug?: string }>();
  const { activeEvent, selectEvent } = useEventContext();
  const slug = slugParam ?? activeEvent?.slug ?? null;
  const navigate = useNavigate();
  const location = useLocation();
  const { t } = useTranslation('management');

  const [photos, setPhotos] = React.useState<TenantPhoto[]>([]);
  const [filter, setFilter] = React.useState<FilterKey>('all');
  const [page, setPage] = React.useState(1);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [busyId, setBusyId] = React.useState<number | null>(null);
  const [totalCount, setTotalCount] = React.useState<number>(0);
  const [hasMore, setHasMore] = React.useState(false);
  const [search, setSearch] = React.useState('');
  const [showFilters, setShowFilters] = React.useState(false);
  const [uploaderFilter, setUploaderFilter] = React.useState('');
  const [onlyFeatured, setOnlyFeatured] = React.useState(false);
  const [onlyHidden, setOnlyHidden] = React.useState(false);
  const [lightbox, setLightbox] = React.useState<TenantPhoto | null>(null);
  const [limits, setLimits] = React.useState<EventLimitSummary | null>(null);
  const [catalogAddons, setCatalogAddons] = React.useState<EventAddonCatalogItem[]>([]);
  const [eventAddons, setEventAddons] = React.useState<EventAddonSummary[]>([]);
  const [busyScope, setBusyScope] = React.useState<string | null>(null);
  const theme = useTheme();
  const text = String(theme.color?.val ?? '#111827');
  const muted = String(theme.gray?.val ?? '#4b5563');
  const border = String(theme.borderColor?.val ?? '#e5e7eb');
  const infoBg = String(theme.blue3?.val ?? '#e8f1ff');
  const infoBorder = String(theme.blue6?.val ?? '#bfdbfe');
  const danger = String(theme.red10?.val ?? '#b91c1c');
  const surface = String(theme.surface?.val ?? '#ffffff');
  const backdrop = String(theme.gray12?.val ?? '#0f172a');

  const baseInputStyle = React.useMemo<React.CSSProperties>(
    () => ({
      width: '100%',
      height: 38,
      borderRadius: 10,
      border: `1px solid ${border}`,
      padding: '0 12px',
      fontSize: 13,
      background: surface,
      color: text,
    }),
    [border, surface, text],
  );
  React.useEffect(() => {
    if (slugParam && activeEvent?.slug !== slugParam) {
      selectEvent(slugParam);
    }
  }, [slugParam, activeEvent?.slug, selectEvent]);

  const load = React.useCallback(async () => {
    if (!slug) return;
    setLoading(true);
    setError(null);
    try {
      const result = await getEventPhotos(slug, {
        page,
        perPage: 20,
        sort: 'desc',
        featured: filter === 'featured' || onlyFeatured,
        status: filter === 'hidden' || onlyHidden ? 'hidden' : undefined,
        search: search || undefined,
      });
      setPhotos((prev) => (page === 1 ? result.photos : [...prev, ...result.photos]));
      setTotalCount(result.meta?.total ?? result.photos.length);
      setLimits(result.limits ?? null);
      const lastPage = result.meta?.last_page ?? 1;
      setHasMore(page < lastPage);
      const [addons, event] = await Promise.all([
        getAddonCatalog().catch(() => [] as EventAddonCatalogItem[]),
        getEvent(slug).catch(() => null),
      ]);
      setCatalogAddons(addons ?? []);
      setEventAddons(event?.addons ?? []);
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('mobilePhotos.loadFailed', 'Fotos konnten nicht geladen werden.')));
      }
    } finally {
      setLoading(false);
    }
  }, [slug, filter, t, page, onlyFeatured, onlyHidden, search]);

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

  React.useEffect(() => {
    if (!location.search || !slug) return;
    const params = new URLSearchParams(location.search);
    if (params.get('addon_success')) {
      toast.success(t('mobileBilling.addonApplied', 'Add-on applied. Limits update shortly.'));
      setPage(1);
      void load();
      params.delete('addon_success');
      navigate({ pathname: location.pathname, search: params.toString() ? `?${params.toString()}` : '' }, { replace: true });
    }
  }, [location.search, slug, load, navigate, t, location.pathname]);

  React.useEffect(() => {
    setPage(1);
  }, [filter, slug]);

  async function toggleVisibility(photo: TenantPhoto) {
    if (!slug) return;
    setBusyId(photo.id);
    try {
      const updated = await updatePhotoVisibility(slug, photo.id, photo.status === 'hidden');
      setPhotos((prev) => prev.map((p) => (p.id === photo.id ? updated : p)));
      setLightbox((prev) => (prev && prev.id === photo.id ? updated : prev));
      toast.success(
        updated.status === 'hidden'
          ? t('mobilePhotos.hideSuccess', 'Photo hidden')
          : t('mobilePhotos.showSuccess', 'Photo shown'),
      );
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('mobilePhotos.visibilityFailed', 'Sichtbarkeit konnte nicht geändert werden.')));
        toast.error(t('mobilePhotos.visibilityFailed', 'Sichtbarkeit konnte nicht geändert werden.'));
      }
    } finally {
      setBusyId(null);
    }
  }

  async function toggleFeature(photo: TenantPhoto) {
    if (!slug) return;
    setBusyId(photo.id);
    try {
      const updated = photo.is_featured ? await unfeaturePhoto(slug, photo.id) : await featurePhoto(slug, photo.id);
      setPhotos((prev) => prev.map((p) => (p.id === photo.id ? updated : p)));
      setLightbox((prev) => (prev && prev.id === photo.id ? updated : prev));
      toast.success(
        updated.is_featured
          ? t('mobilePhotos.featureSuccess', 'Als Highlight markiert')
          : t('mobilePhotos.unfeatureSuccess', 'Highlight entfernt'),
      );
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('mobilePhotos.featureFailed', 'Feature konnte nicht geändert werden.')));
        toast.error(t('mobilePhotos.featureFailed', 'Feature konnte nicht geändert werden.'));
      }
    } finally {
      setBusyId(null);
    }
  }

  return (
    <MobileShell
      activeTab="uploads"
      title={t('mobilePhotos.title', 'Photo moderation')}
      onBack={() => navigate(-1)}
      headerActions={
        <XStack space="$3">
          <Pressable onPress={() => setShowFilters(true)}>
            <Filter size={18} color={text} />
          </Pressable>
          <Pressable onPress={() => load()}>
            <RefreshCcw size={18} color={text} />
          </Pressable>
        </XStack>
      }
    >
      {error ? (
        <MobileCard>
          <Text fontWeight="700" color={danger}>
            {error}
          </Text>
        </MobileCard>
      ) : null}

      <input
        type="search"
        value={search}
          onChange={(e) => {
            setSearch(e.target.value);
            setPage(1);
          }}
        placeholder={t('photos.filters.search', 'Search uploads …')}
        style={{ ...baseInputStyle, marginBottom: 12 }}
      />

      <XStack space="$2">
        {(['all', 'featured', 'hidden'] as FilterKey[]).map((key) => (
          <Pressable key={key} onPress={() => setFilter(key)} style={{ flex: 1 }}>
            <MobileCard
              backgroundColor={filter === key ? infoBg : surface}
              borderColor={filter === key ? infoBorder : border}
              padding="$2.5"
            >
              <Text fontSize="$sm" fontWeight="700" textAlign="center" color={text}>
                {key === 'all'
                  ? t('common.all', 'All')
                  : key === 'featured'
                    ? t('photos.filters.featured', 'Featured')
                    : t('photos.filters.hidden', 'Hidden')}
              </Text>
            </MobileCard>
          </Pressable>
        ))}
      </XStack>

      {loading ? (
        <YStack space="$2">
          {Array.from({ length: 4 }).map((_, idx) => (
            <MobileCard key={`ph-${idx}`} height={100} opacity={0.6} />
          ))}
        </YStack>
      ) : photos.length === 0 ? (
        <MobileCard alignItems="center" justifyContent="center" space="$2">
          <ImageIcon size={28} color={muted} />
          <Text fontSize="$sm" color={muted}>
            {t('mobilePhotos.empty', 'No photos found.')}
          </Text>
        </MobileCard>
      ) : (
        <YStack space="$3">
          <LimitWarnings
            limits={limits}
            addons={catalogAddons}
            onCheckout={(scopeOrKey) => { void handleCheckout(scopeOrKey, slug, catalogAddons, setBusyScope, t); }}
            busyScope={busyScope}
            translate={translateLimits(t)}
            textColor={text}
            borderColor={border}
          />
          <Text fontSize="$sm" color={muted}>
            {t('mobilePhotos.count', '{{count}} photos', { count: totalCount })}
          </Text>
          <div
            style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
              gap: 8,
            }}
          >
            {photos.map((photo) => (
              <Pressable key={photo.id} onPress={() => setLightbox(photo)}>
                <YStack borderRadius={10} overflow="hidden" borderWidth={1} borderColor={border}>
                  <img
                    src={photo.thumbnail_url ?? photo.url ?? undefined}
                    alt={photo.caption ?? 'Photo'}
                    style={{ width: '100%', height: 110, objectFit: 'cover' }}
                  />
                  <XStack position="absolute" top={6} left={6} space="$1">
                    {photo.is_featured ? <PillBadge tone="warning">{t('photos.filters.featured', 'Featured')}</PillBadge> : null}
                    {photo.status === 'hidden' ? <PillBadge tone="muted">{t('photos.filters.hidden', 'Hidden')}</PillBadge> : null}
                  </XStack>
                </YStack>
              </Pressable>
            ))}
          </div>
          {hasMore ? (
            <CTAButton label={t('common.loadMore', 'Mehr laden')} onPress={() => setPage((prev) => prev + 1)} />
          ) : null}
        </YStack>
      )}

      {lightbox ? (
        <div className="fixed inset-0 z-50 bg-black/70 backdrop-blur-sm flex items-center justify-center">
          <div
            style={{
              width: '100%',
              maxWidth: 520,
              margin: '0 16px',
              background: surface,
              borderRadius: 20,
              overflow: 'hidden',
              boxShadow: '0 10px 30px rgba(0,0,0,0.25)',
            }}
          >
            <img
              src={lightbox.url ?? lightbox.thumbnail_url ?? undefined}
              alt={lightbox.caption ?? 'Photo'}
              style={{ width: '100%', maxHeight: '60vh', objectFit: 'contain', background: backdrop }}
            />
            <YStack padding="$3" space="$2">
              <XStack space="$2" alignItems="center">
                <PillBadge tone="muted">{lightbox.uploader_name || t('events.members.roles.guest', 'Guest')}</PillBadge>
                <PillBadge tone="muted">❤️ {lightbox.likes_count ?? 0}</PillBadge>
              </XStack>
              <XStack space="$2" flexWrap="wrap">
                <CTAButton
                  label={
                    busyId === lightbox.id
                      ? t('common.processing', '...')
                      : lightbox.is_featured
                        ? t('photos.actions.unfeature', 'Remove highlight')
                        : t('photos.actions.feature', 'Set highlight')
                  }
                  onPress={() => toggleFeature(lightbox)}
                  style={{ flex: 1, minWidth: 140 }}
                />
                <CTAButton
                  label={
                    busyId === lightbox.id
                      ? t('common.processing', '...')
                      : lightbox.status === 'hidden'
                        ? t('photos.actions.show', 'Show')
                        : t('photos.actions.hide', 'Hide')
                  }
                  onPress={() => toggleVisibility(lightbox)}
                  style={{ flex: 1, minWidth: 140 }}
                />
              </XStack>
              <CTAButton label={t('common.close', 'Close')} tone="ghost" onPress={() => setLightbox(null)} />
            </YStack>
          </div>
        </div>
      ) : null}

      <MobileSheet
        open={showFilters}
        onClose={() => setShowFilters(false)}
        title={t('mobilePhotos.filtersTitle', 'Filter')}
        footer={
          <CTAButton
            label={t('mobilePhotos.applyFilters', 'Apply filters')}
            onPress={() => {
              setPage(1);
              setShowFilters(false);
              void load();
            }}
          />
        }
      >
        <YStack space="$2">
          <Field label={t('mobilePhotos.uploader', 'Uploader')} color={text}>
            <input
              type="text"
              value={uploaderFilter}
              onChange={(e) => setUploaderFilter(e.target.value)}
              placeholder={t('mobilePhotos.uploaderPlaceholder', 'Name or email')}
              style={baseInputStyle}
            />
          </Field>
          <XStack space="$2" alignItems="center">
            <label style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <input
                type="checkbox"
                checked={onlyFeatured}
                onChange={(e) => setOnlyFeatured(e.target.checked)}
              />
              <Text fontSize="$sm" color={text}>
                {t('mobilePhotos.onlyFeatured', 'Only featured')}
              </Text>
            </label>
            <label style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <input
                type="checkbox"
                checked={onlyHidden}
                onChange={(e) => setOnlyHidden(e.target.checked)}
              />
              <Text fontSize="$sm" color={text}>
                {t('mobilePhotos.onlyHidden', 'Only hidden')}
              </Text>
            </label>
          </XStack>
          <CTAButton
            label={t('common.reset', 'Reset')}
            tone="ghost"
            onPress={() => {
              setUploaderFilter('');
              setOnlyFeatured(false);
              setOnlyHidden(false);
            }}
          />
        </YStack>
      </MobileSheet>

      {eventAddons.length ? (
        <YStack marginTop="$3" space="$2">
          <Text fontSize="$sm" color={text} fontWeight="700">
            {t('events.sections.addons.title', 'Add-ons & Upgrades')}
          </Text>
          <EventAddonList addons={eventAddons} textColor={text} mutedColor={muted} />
        </YStack>
      ) : null}
    </MobileShell>
  );
}

function Field({ label, color, children }: { label: string; color: string; children: React.ReactNode }) {
  return (
    <YStack space="$1">
      <Text fontSize="$sm" color={color}>
        {label}
      </Text>
      {children}
    </YStack>
  );
}

type LimitTranslator = (key: string, options?: Record<string, unknown>) => string;

function translateLimits(t: (key: string, defaultValue?: string, options?: Record<string, unknown>) => string): LimitTranslator {
  const defaults: Record<string, string> = {
    photosBlocked: 'Upload limit reached. Buy more photos to continue.',
    photosWarning: '{{remaining}} of {{limit}} photos remaining.',
    guestsBlocked: 'Guest limit reached.',
    guestsWarning: '{{remaining}} of {{limit}} guests remaining.',
    galleryExpired: 'Gallery expired. Extend to keep it online.',
    galleryWarningDay: 'Gallery expires in {{days}} day.',
    galleryWarningDays: 'Gallery expires in {{days}} days.',
    buyMorePhotos: 'Buy more photos',
    extendGallery: 'Extend gallery',
  };
  return (key, options) => t(`limits.${key}`, defaults[key] ?? key, options);
}

function LimitWarnings({
  limits,
  addons,
  onCheckout,
  busyScope,
  translate,
  textColor,
  borderColor,
}: {
  limits: EventLimitSummary | null;
  addons: EventAddonCatalogItem[];
  onCheckout: (scopeOrKey: 'photos' | 'gallery' | string) => void;
  busyScope: string | null;
  translate: LimitTranslator;
  textColor: string;
  borderColor: string;
}) {
  const warnings = React.useMemo(() => buildLimitWarnings(limits, translate), [limits, translate]);

  if (!warnings.length) {
    return null;
  }

  return (
    <YStack space="$2">
      {warnings.map((warning) => (
        <MobileCard key={warning.id} borderColor={borderColor} space="$2">
          <Text fontSize="$sm" color={textColor} fontWeight="700">
            {warning.message}
          </Text>
          {(warning.scope === 'photos' || warning.scope === 'gallery') && addons.length ? (
            <MobileAddonsPicker
              scope={warning.scope}
              addons={addons}
              busy={busyScope === warning.scope}
              onCheckout={onCheckout}
              translate={translate}
            />
          ) : null}
          <CTAButton
            label={
              warning.scope === 'photos'
                ? translate('buyMorePhotos')
                : warning.scope === 'gallery'
                  ? translate('extendGallery')
                  : translate('buyMorePhotos')
            }
            onPress={() => onCheckout(warning.scope)}
            loading={busyScope === warning.scope}
          />
        </MobileCard>
      ))}
    </YStack>
  );
}

function MobileAddonsPicker({
  scope,
  addons,
  busy,
  onCheckout,
  translate,
}: {
  scope: 'photos' | 'gallery';
  addons: EventAddonCatalogItem[];
  busy: boolean;
  onCheckout: (addonKey: string) => void;
  translate: LimitTranslator;
}) {
  const options = React.useMemo(() => {
    const whitelist = scopeDefaults[scope];
    const filtered = addons.filter((addon) => addon.price_id && whitelist.includes(addon.key));
    return filtered.length ? filtered : addons.filter((addon) => addon.price_id);
  }, [addons, scope]);

  const [selected, setSelected] = React.useState<string>(() => options[0]?.key ?? selectAddonKeyForScope(addons, scope));

  React.useEffect(() => {
    if (options[0]?.key) {
      setSelected(options[0].key);
    }
  }, [options]);

  if (!options.length) {
    return null;
  }

  return (
    <XStack space="$2" alignItems="center">
      <select
        value={selected}
        onChange={(event) => setSelected(event.target.value)}
        style={{
          flex: 1,
          height: 40,
          borderRadius: 10,
          border: '1px solid #e5e7eb',
          padding: '0 12px',
          fontSize: 13,
          background: '#fff',
        }}
      >
        {options.map((addon) => (
          <option key={addon.key} value={addon.key}>
            {addon.label ?? addon.key}
          </option>
        ))}
      </select>
      <CTAButton
        label={scope === 'gallery' ? translate('extendGallery') : translate('buyMorePhotos')}
        disabled={!selected || busy}
        onPress={() => selected && onCheckout(selected)}
        loading={busy}
      />
    </XStack>
  );
}

function EventAddonList({ addons, textColor, mutedColor }: { addons: EventAddonSummary[]; textColor: string; mutedColor: string }) {
  return (
    <YStack space="$2">
      {addons.map((addon) => (
        <MobileCard key={addon.id} borderColor="#e5e7eb" space="$1.5">
          <XStack alignItems="center" justifyContent="space-between">
            <Text fontSize="$sm" fontWeight="700" color={textColor}>
              {addon.label ?? addon.key}
            </Text>
            <PillBadge tone={addon.status === 'completed' ? 'success' : addon.status === 'pending' ? 'warning' : 'muted'}>
              {addon.status}
            </PillBadge>
          </XStack>
          <Text fontSize="$xs" color={mutedColor}>
            {addon.purchased_at ? new Date(addon.purchased_at).toLocaleString() : '—'}
          </Text>
          <XStack space="$2" marginTop="$1" flexWrap="wrap">
            {addon.extra_photos ? <PillBadge tone="muted">+{addon.extra_photos} photos</PillBadge> : null}
            {addon.extra_guests ? <PillBadge tone="muted">+{addon.extra_guests} guests</PillBadge> : null}
            {addon.extra_gallery_days ? <PillBadge tone="muted">+{addon.extra_gallery_days} days</PillBadge> : null}
          </XStack>
        </MobileCard>
      ))}
    </YStack>
  );
}

async function handleCheckout(
  scopeOrKey: 'photos' | 'gallery' | string,
  slug: string | null,
  addons: EventAddonCatalogItem[],
  setBusyScope: (scope: string | null) => void,
  t: (key: string, defaultValue?: string) => string,
): Promise<void> {
  if (!slug) return;
  const scope = scopeOrKey === 'photos' || scopeOrKey === 'gallery' ? scopeOrKey : scopeOrKey.includes('gallery') ? 'gallery' : 'photos';
  const addonKey = scopeOrKey === 'photos' || scopeOrKey === 'gallery' ? selectAddonKeyForScope(addons, scope) : scopeOrKey;
  const currentUrl = typeof window !== 'undefined' ? `${window.location.origin}${adminPath(`/mobile/events/${slug}/photos`)}` : '';
  const successUrl = `${currentUrl}?addon_success=1`;
  setBusyScope(scope);
  try {
    const checkout = await createEventAddonCheckout(slug, {
      addon_key: addonKey,
      quantity: 1,
      success_url: successUrl,
      cancel_url: currentUrl,
    });
    if (checkout.checkout_url) {
      window.location.href = checkout.checkout_url;
    } else {
      toast.error(t('mobileBilling.checkoutUnavailable', 'Checkout unavailable right now.'));
    }
  } catch (err) {
    toast.error(getApiErrorMessage(err, t('mobileBilling.checkoutFailed', 'Checkout failed.')));
  } finally {
    setBusyScope(null);
  }
}
