import React from 'react';
import { useParams } from 'react-router-dom';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Button } from '@tamagui/button';
import { Download, Share2 } from 'lucide-react';
import { Sheet } from '@tamagui/sheet';
import StandaloneShell from '../components/StandaloneShell';
import SurfaceCard from '../components/SurfaceCard';
import EventLogo from '../components/EventLogo';
import { fetchGalleryMeta, fetchGalleryPhotos, type GalleryMetaResponse, type GalleryPhotoResource } from '@/guest/services/galleryApi';
import { createPhotoShareLink } from '@/guest/services/photosApi';
import { useTranslation } from '@/guest/i18n/useTranslation';
import { EventBrandingProvider } from '@/guest/context/EventBrandingContext';
import { mapEventBranding } from '../lib/eventBranding';
import { BrandingTheme } from '../lib/brandingTheme';
import { useGuestThemeVariant } from '../lib/guestTheme';

type GalleryState = {
  meta: GalleryMetaResponse | null;
  photos: GalleryPhotoResource[];
  cursor: string | null;
  loading: boolean;
  loadingMore: boolean;
  error: string | null;
  expired: boolean;
};

const INITIAL_STATE: GalleryState = {
  meta: null,
  photos: [],
  cursor: null,
  loading: true,
  loadingMore: false,
  error: null,
  expired: false,
};

const PAGE_SIZE = 30;

export default function PublicGalleryScreen() {
  const { token } = useParams<{ token: string }>();
  const { t, locale } = useTranslation();
  const [state, setState] = React.useState<GalleryState>(INITIAL_STATE);
  const [selected, setSelected] = React.useState<GalleryPhotoResource | null>(null);
  const [shareLoading, setShareLoading] = React.useState(false);
  const sentinelRef = React.useRef<HTMLDivElement | null>(null);

  const branding = React.useMemo(() => {
    if (!state.meta) return null;
    return mapEventBranding(state.meta.branding ?? null);
  }, [state.meta]);
  const { isDark } = useGuestThemeVariant(branding);
  const mutedText = isDark ? 'rgba(248, 250, 252, 0.7)' : 'rgba(15, 23, 42, 0.65)';

  const loadInitial = React.useCallback(async () => {
    if (!token) return;
    setState((prev) => ({ ...prev, loading: true, error: null, expired: false, photos: [], cursor: null }));
    try {
      const meta = await fetchGalleryMeta(token, locale);
      const photoResponse = await fetchGalleryPhotos(token, null, PAGE_SIZE);
      setState((prev) => ({
        ...prev,
        meta,
        photos: photoResponse.data,
        cursor: photoResponse.next_cursor,
        loading: false,
      }));
    } catch (error) {
      const err = error as Error & { code?: string | number };
      if (err.code === 'gallery_expired' || err.code === 410) {
        setState((prev) => ({ ...prev, loading: false, expired: true }));
      } else {
        setState((prev) => ({ ...prev, loading: false, error: err.message || t('galleryPublic.loadError') }));
      }
    }
  }, [locale, t, token]);

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

  const loadMore = React.useCallback(async () => {
    if (!token || !state.cursor || state.loadingMore) return;
    setState((prev) => ({ ...prev, loadingMore: true }));
    try {
      const response = await fetchGalleryPhotos(token, state.cursor, PAGE_SIZE);
      setState((prev) => ({
        ...prev,
        photos: [...prev.photos, ...response.data],
        cursor: response.next_cursor,
        loadingMore: false,
      }));
    } catch (error) {
      const err = error as Error;
      setState((prev) => ({ ...prev, loadingMore: false, error: err.message || t('galleryPublic.loadError') }));
    }
  }, [state.cursor, state.loadingMore, t, token]);

  React.useEffect(() => {
    if (!state.cursor || !sentinelRef.current) return;
    const observer = new IntersectionObserver((entries) => {
      if (entries[0]?.isIntersecting) loadMore();
    }, { rootMargin: '400px', threshold: 0 });
    observer.observe(sentinelRef.current);
    return () => observer.disconnect();
  }, [state.cursor, loadMore]);

  const content = (
    <StandaloneShell>
      <SurfaceCard glow>
        <XStack alignItems="center" gap="$3">
          <EventLogo name={state.meta?.event?.name ?? t('galleryPage.hero.eventFallback', 'Event')} size="s" />
          <YStack gap="$1">
            <Text fontSize="$4" fontWeight="$7">
              {t('galleryPublic.title')}
            </Text>
            <Text fontSize="$2" color={mutedText}>
              {state.meta?.event?.name ?? t('galleryPage.hero.eventFallback', 'Event')}
            </Text>
          </YStack>
        </XStack>
      </SurfaceCard>

      {state.loading ? (
        <SurfaceCard>
          <Text fontSize="$3" color={mutedText}>
            {t('galleryPublic.loading')}
          </Text>
        </SurfaceCard>
      ) : state.expired ? (
        <SurfaceCard>
          <Text fontSize="$4" fontWeight="$7">
            {t('galleryPublic.expiredTitle')}
          </Text>
          <Text fontSize="$2" color={mutedText} marginTop="$2">
            {t('galleryPublic.expiredDescription')}
          </Text>
        </SurfaceCard>
      ) : state.error ? (
        <SurfaceCard>
          <Text fontSize="$3" fontWeight="$7">
            {t('galleryPublic.loadError')}
          </Text>
          <Text fontSize="$2" color={mutedText} marginTop="$2">
            {state.error}
          </Text>
        </SurfaceCard>
      ) : state.photos.length === 0 ? (
        <SurfaceCard>
          <Text fontSize="$4" fontWeight="$7">
            {t('galleryPublic.emptyTitle')}
          </Text>
          <Text fontSize="$2" color={mutedText} marginTop="$2">
            {t('galleryPublic.emptyDescription')}
          </Text>
        </SurfaceCard>
      ) : (
        <YStack gap="$3">
          <XStack gap="$3">
            <YStack flex={1} gap="$3">
              {state.photos.filter((_, index) => index % 2 === 0).map((photo, index) => (
                <Button key={photo.id} unstyled onPress={() => setSelected(photo)}>
                  <SurfaceCard padding={0} overflow="hidden" height={150 + (index % 3) * 32}>
                    <YStack
                      flex={1}
                      style={{
                        backgroundImage: `url(${photo.thumbnail_url ?? photo.full_url})`,
                        backgroundSize: 'cover',
                        backgroundPosition: 'center',
                      }}
                    />
                  </SurfaceCard>
                </Button>
              ))}
            </YStack>
            <YStack flex={1} gap="$3">
              {state.photos.filter((_, index) => index % 2 === 1).map((photo, index) => (
                <Button key={photo.id} unstyled onPress={() => setSelected(photo)}>
                  <SurfaceCard padding={0} overflow="hidden" height={140 + (index % 3) * 28}>
                    <YStack
                      flex={1}
                      style={{
                        backgroundImage: `url(${photo.thumbnail_url ?? photo.full_url})`,
                        backgroundSize: 'cover',
                        backgroundPosition: 'center',
                      }}
                    />
                  </SurfaceCard>
                </Button>
              ))}
            </YStack>
          </XStack>
          {state.loadingMore ? (
            <SurfaceCard>
              <Text fontSize="$2" color={mutedText}>
                {t('galleryPublic.loadingMore')}
              </Text>
            </SurfaceCard>
          ) : null}
          <div ref={sentinelRef} />
        </YStack>
      )}

      <Sheet
        open={Boolean(selected)}
        onOpenChange={(next) => {
          if (!next) setSelected(null);
        }}
        snapPoints={[92]}
        position={selected ? 0 : -1}
        modal
      >
      <Sheet.Overlay {...({ backgroundColor: isDark ? 'rgba(15, 23, 42, 0.6)' : 'rgba(15, 23, 42, 0.3)' } as any)} />
      <Sheet.Frame padding="$4" backgroundColor="$surface" borderTopLeftRadius="$6" borderTopRightRadius="$6">
          <Sheet.Handle height={5} width={52} backgroundColor="#CBD5E1" borderRadius={999} marginBottom="$3" />
          {selected ? (
            <YStack gap="$4">
              <YStack
                height={360}
                borderRadius="$card"
                backgroundColor="$muted"
                overflow="hidden"
                alignItems="center"
                justifyContent="center"
              >
                <img
                  src={selected.full_url ?? selected.thumbnail_url ?? ''}
                  alt={selected.guest_name ?? t('galleryPublic.lightboxGuestFallback', 'Guest')}
                  style={{ width: '100%', height: '100%', objectFit: 'contain' }}
                />
              </YStack>
              <XStack alignItems="center" justifyContent="space-between" flexWrap="wrap" gap="$2">
                <Text fontSize="$3" fontWeight="$7">
                  {selected.likes_count ? `${selected.likes_count} ❤` : ''}
                </Text>
                <XStack gap="$2">
                  {(state.meta?.event?.guest_downloads_enabled ?? true) && selected.download_url ? (
                    <Button size="$3" borderRadius="$pill" backgroundColor="$primary" asChild>
                      <a href={selected.download_url} target="_blank" rel="noopener noreferrer">
                        <Download size={16} color="white" />
                        <Text fontSize="$2" fontWeight="$7" color="white">
                          {t('galleryPublic.download')}
                        </Text>
                      </a>
                    </Button>
                  ) : null}
                  {(state.meta?.event?.guest_sharing_enabled ?? true) ? (
                    <Button
                      size="$3"
                      borderRadius="$pill"
                      backgroundColor={isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(15, 23, 42, 0.06)'}
                      borderWidth={1}
                      borderColor={isDark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(15, 23, 42, 0.12)'}
                      onPress={async () => {
                        if (!token || !selected) return;
                        setShareLoading(true);
                        try {
                          const payload = await createPhotoShareLink(token, selected.id);
                          const shareData: ShareData = {
                            title: selected.guest_name ?? t('share.title', 'Geteiltes Foto'),
                            text: t('share.shareText', 'Check out this moment on Fotospiel.'),
                            url: payload.url,
                          };
                          if (navigator.share && (!navigator.canShare || navigator.canShare(shareData))) {
                            await navigator.share(shareData).catch(() => undefined);
                          } else if (payload.url) {
                            await navigator.clipboard.writeText(payload.url);
                          }
                        } finally {
                          setShareLoading(false);
                        }
                      }}
                      disabled={shareLoading}
                    >
                      <Share2 size={16} color={isDark ? '#F8FAFF' : '#0F172A'} />
                      <Text fontSize="$2" fontWeight="$6">
                        {shareLoading ? t('common.actions.loading', 'Loading...') : t('share.shareCta', 'Teilen')}
                      </Text>
                    </Button>
                  ) : null}
                </XStack>
              </XStack>
            </YStack>
          ) : null}
        </Sheet.Frame>
      </Sheet>
    </StandaloneShell>
  );

  if (!branding) {
    return content;
  }

  return (
    <EventBrandingProvider branding={branding}>
      <BrandingTheme>{content}</BrandingTheme>
    </EventBrandingProvider>
  );
}
