import React from 'react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Button } from '@tamagui/button';
import { Image as ImageIcon, Filter } from 'lucide-react';
import AppShell from '../components/AppShell';
import PhotoFrameTile from '../components/PhotoFrameTile';
import { useEventData } from '../context/EventDataContext';
import { fetchGallery } from '../services/photosApi';
import { usePollGalleryDelta } from '../hooks/usePollGalleryDelta';
import { useGuestThemeVariant } from '../lib/guestTheme';
import { useTranslation } from '@/guest/i18n/useTranslation';
import { useLocale } from '@/guest/i18n/LocaleContext';
import { useNavigate } from 'react-router-dom';
import { buildEventPath } from '../lib/routes';

type GalleryFilter = 'latest' | 'popular' | 'mine' | 'photobooth';

type GalleryTile = {
  id: number;
  imageUrl: string;
  likes: number;
  createdAt?: string | null;
  ingestSource?: string | null;
  sessionId?: string | null;
};

function normalizeImageUrl(src?: string | null) {
  if (!src) {
    return '';
  }

  if (/^https?:/i.test(src)) {
    return src;
  }

  let cleanPath = src.replace(/^\/+/g, '').replace(/\/+/g, '/');
  if (!cleanPath.startsWith('storage/')) {
    cleanPath = `storage/${cleanPath}`;
  }

  return `/${cleanPath}`.replace(/\/+/g, '/');
}

export default function GalleryScreen() {
  const { token } = useEventData();
  const { t } = useTranslation();
  const { locale } = useLocale();
  const navigate = useNavigate();
  const { isDark } = useGuestThemeVariant();
  const cardBorder = isDark ? 'rgba(255, 255, 255, 0.12)' : 'rgba(15, 23, 42, 0.12)';
  const cardShadow = isDark ? '0 18px 40px rgba(2, 6, 23, 0.4)' : '0 16px 30px rgba(15, 23, 42, 0.12)';
  const mutedButton = isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(15, 23, 42, 0.06)';
  const mutedButtonBorder = isDark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(15, 23, 42, 0.12)';
  const [photos, setPhotos] = React.useState<GalleryTile[]>([]);
  const [loading, setLoading] = React.useState(false);
  const { data: delta } = usePollGalleryDelta(token ?? null, { locale });
  const [filter, setFilter] = React.useState<GalleryFilter>('latest');

  React.useEffect(() => {
    if (!token) {
      setPhotos([]);
      return;
    }

    let active = true;
    setLoading(true);

    fetchGallery(token, { limit: 18, locale })
      .then((response) => {
        if (!active) return;
        const list = Array.isArray(response.data) ? response.data : [];
        const mapped = list
          .map((photo) => {
            const record = photo as Record<string, unknown>;
            const id = Number(record.id ?? 0);
            const likesCount = typeof record.likes_count === 'number' ? record.likes_count : 0;
            const imageUrl = normalizeImageUrl(
              (record.thumbnail_url as string | null | undefined)
                ?? (record.thumbnail_path as string | null | undefined)
                ?? (record.file_path as string | null | undefined)
                ?? (record.full_url as string | null | undefined)
                ?? (record.url as string | null | undefined)
                ?? (record.image_url as string | null | undefined)
            );
            return {
              id,
              imageUrl,
              likes: likesCount,
              createdAt: typeof record.created_at === 'string' ? record.created_at : null,
              ingestSource: typeof record.ingest_source === 'string' ? record.ingest_source : null,
              sessionId: typeof record.session_id === 'string' ? record.session_id : null,
            };
          })
          .filter((item) => item.id && item.imageUrl);
        setPhotos(mapped);
      })
      .catch((error) => {
        console.error('Failed to load gallery', error);
        if (active) {
          setPhotos([]);
        }
      })
      .finally(() => {
        if (active) {
          setLoading(false);
        }
      });

    return () => {
      active = false;
    };
  }, [token, locale]);

  const myPhotoIds = React.useMemo(() => {
    try {
      const raw = localStorage.getItem('my-photo-ids');
      return new Set<number>(raw ? JSON.parse(raw) : []);
    } catch {
      return new Set<number>();
    }
  }, [token]);

  const filteredPhotos = React.useMemo(() => {
    let list = photos.slice();
    if (filter === 'popular') {
      list.sort((a, b) => (b.likes ?? 0) - (a.likes ?? 0));
    } else if (filter === 'mine') {
      list = list.filter((photo) => myPhotoIds.has(photo.id));
    } else if (filter === 'photobooth') {
      list = list.filter((photo) => photo.ingestSource === 'photobooth');
      list.sort((a, b) => new Date(b.createdAt ?? 0).getTime() - new Date(a.createdAt ?? 0).getTime());
    } else {
      list.sort((a, b) => new Date(b.createdAt ?? 0).getTime() - new Date(a.createdAt ?? 0).getTime());
    }
    return list;
  }, [filter, myPhotoIds, photos]);

  const displayPhotos = filteredPhotos;
  const leftColumn = displayPhotos.filter((_, index) => index % 2 === 0);
  const rightColumn = displayPhotos.filter((_, index) => index % 2 === 1);

  React.useEffect(() => {
    if (filter === 'photobooth' && !photos.some((photo) => photo.ingestSource === 'photobooth')) {
      setFilter('latest');
    }
  }, [filter, photos]);
  const newUploads = React.useMemo(() => {
    if (delta.photos.length === 0) {
      return 0;
    }
    const existing = new Set(photos.map((item) => item.id));
    return delta.photos.reduce((count, photo) => {
      const id = Number((photo as Record<string, unknown>).id ?? 0);
      if (id && !existing.has(id)) {
        return count + 1;
      }
      return count;
    }, 0);
  }, [delta.photos, photos]);
  const openLightbox = React.useCallback(
    (photoId: number) => {
      if (!token) return;
      navigate(buildEventPath(token, `/photo/${photoId}`));
    },
    [navigate, token]
  );

  React.useEffect(() => {
    if (delta.photos.length === 0) {
      return;
    }
    setPhotos((prev) => {
      const existing = new Set(prev.map((item) => item.id));
      const mapped = delta.photos
        .map((photo) => {
          const record = photo as Record<string, unknown>;
          const id = Number(record.id ?? 0);
          const likesCount = typeof record.likes_count === 'number' ? record.likes_count : 0;
          const imageUrl = normalizeImageUrl(
            (record.thumbnail_url as string | null | undefined)
              ?? (record.thumbnail_path as string | null | undefined)
              ?? (record.file_path as string | null | undefined)
              ?? (record.full_url as string | null | undefined)
              ?? (record.url as string | null | undefined)
              ?? (record.image_url as string | null | undefined)
          );
          if (!id || !imageUrl || existing.has(id)) {
            return null;
          }
          return {
            id,
            imageUrl,
            likes: likesCount,
            createdAt: typeof record.created_at === 'string' ? record.created_at : null,
            ingestSource: typeof record.ingest_source === 'string' ? record.ingest_source : null,
            sessionId: typeof record.session_id === 'string' ? record.session_id : null,
          } satisfies GalleryTile;
        })
        .filter(Boolean) as GalleryTile[];
      if (mapped.length === 0) {
        return prev;
      }
      return [...mapped, ...prev];
    });
  }, [delta.photos]);


  return (
    <AppShell>
      <YStack gap="$4">
        <YStack
          padding="$4"
          borderRadius="$card"
          backgroundColor="$surface"
          borderWidth={1}
          borderColor={cardBorder}
          gap="$3"
          style={{
            boxShadow: cardShadow,
          }}
        >
          <XStack alignItems="center" justifyContent="space-between">
            <XStack alignItems="center" gap="$2">
              <ImageIcon size={18} color={isDark ? '#F8FAFF' : '#0F172A'} />
              <Text fontSize="$4" fontWeight="$7">
                {t('galleryPage.title', 'Gallery')}
              </Text>
            </XStack>
            <Button
              size="$3"
              backgroundColor={mutedButton}
              borderRadius="$pill"
              borderWidth={1}
              borderColor={mutedButtonBorder}
            >
              <Filter size={16} color={isDark ? '#F8FAFF' : '#0F172A'} />
            </Button>
          </XStack>
          <XStack gap="$2" flexWrap="wrap">
            {(
              [
                { value: 'latest', label: t('galleryPage.filters.latest', 'Newest') },
                { value: 'popular', label: t('galleryPage.filters.popular', 'Popular') },
                { value: 'mine', label: t('galleryPage.filters.mine', 'My photos') },
                photos.some((photo) => photo.ingestSource === 'photobooth')
                  ? { value: 'photobooth', label: t('galleryPage.filters.photobooth', 'Photo booth') }
                  : null,
              ].filter(Boolean) as Array<{ value: GalleryFilter; label: string }>
            ).map((chip) => (
              <Button
                key={chip.value}
                size="$3"
                backgroundColor={filter === chip.value ? '$primary' : mutedButton}
                borderRadius="$pill"
                borderWidth={1}
                borderColor={filter === chip.value ? '$primary' : mutedButtonBorder}
                onPress={() => setFilter(chip.value)}
              >
                <Text fontSize="$2" fontWeight="$6" color={filter === chip.value ? '#FFFFFF' : undefined}>
                  {chip.label}
                </Text>
              </Button>
            ))}
          </XStack>
        </YStack>

        <XStack gap="$3">
          <YStack flex={1} gap="$3">
            {(loading || leftColumn.length === 0 ? Array.from({ length: 5 }, (_, index) => index) : leftColumn).map(
              (tile, index) => {
                if (typeof tile === 'number') {
                  return <PhotoFrameTile key={`left-${tile}`} height={140 + (index % 3) * 24} shimmer shimmerDelayMs={200 + index * 120} />;
                }
                return (
                  <Button
                    key={tile.id}
                    unstyled
                    onPress={() => openLightbox(tile.id)}
                  >
                    <PhotoFrameTile height={140 + (index % 3) * 24}>
                      <YStack flex={1} width="100%" height="100%" alignItems="center" justifyContent="center">
                        <img
                          src={tile.imageUrl}
                          alt={t('galleryPage.photo.alt', { id: tile.id }, 'Photo {id}')}
                          style={{ width: '100%', height: '100%', objectFit: 'contain' }}
                        />
                      </YStack>
                    </PhotoFrameTile>
                  </Button>
                );
              }
            )}
          </YStack>
          <YStack flex={1} gap="$3">
            {(loading || rightColumn.length === 0 ? Array.from({ length: 5 }, (_, index) => index) : rightColumn).map(
              (tile, index) => {
                if (typeof tile === 'number') {
                  return <PhotoFrameTile key={`right-${tile}`} height={120 + (index % 3) * 28} shimmer shimmerDelayMs={260 + index * 140} />;
                }
                return (
                  <Button
                    key={tile.id}
                    unstyled
                    onPress={() => openLightbox(tile.id)}
                  >
                    <PhotoFrameTile height={120 + (index % 3) * 28}>
                      <YStack flex={1} width="100%" height="100%" alignItems="center" justifyContent="center">
                        <img
                          src={tile.imageUrl}
                          alt={t('galleryPage.photo.alt', { id: tile.id }, 'Photo {id}')}
                          style={{ width: '100%', height: '100%', objectFit: 'contain' }}
                        />
                      </YStack>
                    </PhotoFrameTile>
                  </Button>
                );
              }
            )}
          </YStack>
        </XStack>

        <YStack
          padding="$4"
          borderRadius="$card"
          backgroundColor="$surface"
          borderWidth={1}
          borderColor={cardBorder}
          gap="$1"
          style={{
            boxShadow: cardShadow,
          }}
        >
          <Text fontSize="$3" fontWeight="$7">
            {t('galleryPage.feed.title', 'Live feed')}
          </Text>
          <Text fontSize="$2" color="$color" opacity={0.7}>
            {newUploads > 0
              ? t('galleryPage.feed.newUploads', { count: newUploads }, '{count} new uploads just landed.')
              : t('galleryPage.feed.description', 'Updated every few seconds.')}
          </Text>
        </YStack>
      </YStack>
    </AppShell>
  );
}
