import { BackButton } from '@/components/ui/back-button';
import { getTagByName, type TagTemplate } from '@/lib/api/tags';
import { getTemplateById } from '@/lib/api/templates';
import Feather from '@expo/vector-icons/Feather';
import { Stack, router, useLocalSearchParams } from 'expo-router';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  ActivityIndicator,
  Image,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

type TemplateFrame = {
  id: string;
  title: string;
  uri: string;
  accent: string;
};

type TemplateLike = {
  id: string;
  title?: string | null;
  titleEn?: string | null;
  coverImageUrl?: string | null;
  previewUrl?: string | null;
};

const ACCENT_COLORS = ['#D1FF00', '#FF7A45', '#7A8BFF', '#FF5F6D', '#21D4FD', '#FFAA00'];
const FALLBACK_PREVIEW =
  'https://images.unsplash.com/photo-1542204165-0198c1e21a3b?auto=format&fit=crop&w=1200&q=80';

const createFrame = (template: TemplateLike, index = 0): TemplateFrame => {
  const title = (template.titleEn || template.title || '').trim() || 'Untitled Template';
  const uri = template.coverImageUrl || template.previewUrl || FALLBACK_PREVIEW;

  return {
    id: template.id,
    title,
    uri,
    accent: ACCENT_COLORS[index % ACCENT_COLORS.length],
  };
};

const mapTagTemplates = (templates: TagTemplate[]): TemplateFrame[] =>
  templates.map((template, index) => createFrame(template, index));

const quickActions = [
  { id: 'upscale', label: 'Upscale' },
  { id: 'collect', label: 'Collect' },
  { id: 'download', label: 'Download' },
];

const PreviewFrame = React.memo<{
  frame: TemplateFrame;
  isActive: boolean;
  onPress: () => void;
}>(({ frame, isActive, onPress }) => {
  return (
    <TouchableOpacity
      activeOpacity={0.85}
      onPress={onPress}
      style={[
        styles.previewFrame,
        { borderColor: isActive ? frame.accent : 'rgba(255,255,255,0.08)' },
        isActive && styles.previewFrameActive,
      ]}
    >
      <Image source={{ uri: frame.uri }} style={styles.previewImage} />
    </TouchableOpacity>
  );
});

PreviewFrame.displayName = 'PreviewFrame';

const CACHE_DURATION = 5 * 60 * 1000;
const cache = new Map<string, { data: TemplateFrame[]; timestamp: number }>();

export default function TemplateDetailScreen() {
  const { id } = useLocalSearchParams<{ id: string }>();
  const [looks, setLooks] = useState<TemplateFrame[]>([]);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [menuVisible, setMenuVisible] = useState(false);
  const [loadingLooks, setLoadingLooks] = useState(true);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [retryTrigger, setRetryTrigger] = useState(0);
  const abortControllerRef = useRef<AbortController | null>(null);
  const imageCache = useRef(new Set<string>());

  const getCachedData = useCallback((key: string) => {
    const cached = cache.get(key);
    if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
      return cached.data;
    }
    return null;
  }, []);

  const setCachedData = useCallback((key: string, data: TemplateFrame[]) => {
    cache.set(key, { data, timestamp: Date.now() });
  }, []);

  const preloadImage = useCallback((uri: string) => {
    if (imageCache.current.has(uri)) {
      return;
    }
    Image.prefetch(uri).then(() => {
      imageCache.current.add(uri);
    }).catch(() => {
    });
  }, []);

  useEffect(() => {
    abortControllerRef.current?.abort();
    abortControllerRef.current = new AbortController();
    const signal = abortControllerRef.current.signal;

    let isMounted = true;

    const loadByTagName = async (tagName?: string | null): Promise<TemplateFrame[]> => {
      if (!tagName) {
        return [];
      }

      const cacheKey = `tag:${tagName}`;
      const cached = getCachedData(cacheKey);
      if (cached) {
        return cached;
      }

      try {
        const response = await getTagByName(tagName);
        if (response.success && response.data?.templates?.length) {
          const templates = mapTagTemplates(response.data.templates);
          setCachedData(cacheKey, templates);
          return templates;
        }
      } catch (tagError) {
        console.warn('Failed to load tag templates:', tagError);
      }

      return [];
    };

    const hydrateLooks = async () => {
      if (!id || typeof id !== 'string') {
        setLooks([]);
        setSelectedId(null);
        setErrorMessage('Missing template identifier');
        setLoadingLooks(false);
        return;
      }

      setLoadingLooks(true);
      setErrorMessage(null);

      try {
        const templateResponse = await getTemplateById(id);
        if (!signal.aborted && templateResponse.success && templateResponse.data) {
          const template = templateResponse.data;
          const primaryTagName = template.tags?.[0]?.nameEn || template.tags?.[0]?.name;

          const [relatedFrames, mainFrame] = await Promise.allSettled([
            loadByTagName(primaryTagName),
            Promise.resolve(createFrame(template, 0))
          ]);

          const frames: TemplateFrame[] = [];

          if (relatedFrames.status === 'fulfilled' && relatedFrames.value.length > 0) {
            frames.push(...relatedFrames.value);
          } else {
            frames.push(mainFrame.status === 'fulfilled' ? mainFrame.value : createFrame(template, 0));
          }

          if (!isMounted || signal.aborted) {
            return;
          }

          setLooks(frames);
          setCachedData(`template:${id}`, frames);

          const preferredId =
            frames.find(frame => frame.id === id)?.id ??
            frames[0]?.id ??
            template.id;

          setSelectedId(preferredId);

          frames.slice(0, 3).forEach(frame => preloadImage(frame.uri));
        } else {
          if (!isMounted || signal.aborted) {
            return;
          }
          setErrorMessage('Template not found');
          setLooks([]);
          setSelectedId(null);
        }
      } catch (templateError) {
        if (!isMounted || signal.aborted) {
          return;
        }
        console.warn('Failed to fetch template detail:', templateError);
        setErrorMessage('Failed to load template');
        setLooks([]);
        setSelectedId(null);
      } finally {
        if (isMounted && !signal.aborted) {
          setLoadingLooks(false);
        }
      }
    };

    hydrateLooks();

    return () => {
      isMounted = false;
      abortControllerRef.current?.abort();
    };
  }, [id, getCachedData, setCachedData, preloadImage]);

  const current = useMemo(() => {
    if (looks.length === 0) {
      return null;
    }

    if (!selectedId) {
      return looks[0];
    }

    return looks.find(look => look.id === selectedId) ?? looks[0];
  }, [looks, selectedId]);

  const resolvedTemplateId = current?.id ?? (typeof id === 'string' ? id : '');
  const heroImageUri = current?.uri ?? FALLBACK_PREVIEW;
  const infoTitle = current?.title ?? 'Loading template';

  const handleRetry = useCallback(() => {
    cache.delete(`template:${id}`);
    cache.delete(`tag:${current?.title}`);
    setErrorMessage(null);
    setLoadingLooks(true);
    setRetryTrigger(prev => prev + 1);
  }, [id, current?.title]);

  useEffect(() => {
    if (retryTrigger > 0) {
      const newController = new AbortController();
      abortControllerRef.current = newController;
    }
  }, [retryTrigger]);

  const handleGenerate = () => {
    if (!resolvedTemplateId) {
      return;
    }

    router.push(`/templates/${resolvedTemplateId}/form`);
  };

  return (
    <>
      <Stack.Screen options={{ headerShown: false }} />

      <View style={styles.canvas}>
        <SafeAreaView style={styles.safeArea} edges={['top', 'left', 'right']}>
        <View style={styles.headerBar}>
          <BackButton onPress={() => router.back()} />

          <Text style={styles.headerTitle} numberOfLines={1}>
            {infoTitle}
          </Text>

          <View style={styles.headerPlaceholder} />
        </View>

        <ScrollView
          style={styles.body}
          showsVerticalScrollIndicator={false}
          contentContainerStyle={styles.scrollContent}
        >
          {loadingLooks && (
            <View style={styles.loadingState}>
              <ActivityIndicator color="#D1FF00" />
              <Text style={styles.loadingLabel}>Loading templates...</Text>
            </View>
          )}

          {!loadingLooks && errorMessage && (
            <View style={styles.errorBanner}>
              <Text style={styles.errorText}>{errorMessage}</Text>
              <TouchableOpacity style={styles.retryButton} onPress={handleRetry}>
                <Text style={styles.retryLabel}>Retry</Text>
              </TouchableOpacity>
            </View>
          )}

          <View style={styles.topCarousel}>
            {looks.length > 0 ? (
              <ScrollView
                horizontal
                showsHorizontalScrollIndicator={false}
                contentContainerStyle={styles.carouselContent}
              >
                {looks.map(look => (
                  <PreviewFrame
                    key={look.id}
                    frame={look}
                    isActive={look.id === selectedId}
                    onPress={() => setSelectedId(look.id)}
                  />
                ))}
              </ScrollView>
            ) : (
              !loadingLooks && (
                <View style={styles.emptyCarousel}>
                  <Text style={styles.emptyCarouselText}>Nothing to show yet</Text>
                </View>
              )
            )}
          </View>

          <View style={styles.heroStage}>
            <Image source={{ uri: heroImageUri }} style={styles.heroImage} />
          </View>

          <View style={styles.bottomInfoRow}>
            <View style={styles.infoCard}>
              <Image source={{ uri: heroImageUri }} style={styles.infoThumbnail} />
              <Text style={styles.infoTitle} numberOfLines={1}>
                {infoTitle}
              </Text>
            </View>

            <TouchableOpacity
              style={styles.menuTrigger}
              activeOpacity={0.85}
              onPress={() => setMenuVisible(prev => !prev)}
            >
              <View style={styles.menuDots}>
                <View style={styles.dot} />
                <View style={[styles.dot, styles.dotMiddle]} />
                <View style={styles.dot} />
              </View>
            </TouchableOpacity>
          </View>

          <TouchableOpacity
            style={[
              styles.generateButton,
              !resolvedTemplateId && styles.generateButtonDisabled,
            ]}
            activeOpacity={0.9}
            onPress={handleGenerate}
            disabled={!resolvedTemplateId}
          >
            <Feather name="star" size={20} color="#050505" />
            <Text style={styles.generateLabel}>Generate Video</Text>
          </TouchableOpacity>
        </ScrollView>

        {menuVisible && (
          <View style={styles.menuPanel}>
            {quickActions.map(action => (
              <TouchableOpacity
                key={action.id}
                activeOpacity={0.85}
                style={styles.menuItem}
                onPress={() => setMenuVisible(false)}
              >
                <Text style={styles.menuLabel}>{action.label}</Text>
              </TouchableOpacity>
            ))}
          </View>
        )}
      </SafeAreaView>
    </View>
    </>
  );
}

const styles = StyleSheet.create({
  canvas: {
    flex: 1,
    backgroundColor: '#040404',
  },
  safeArea: {
    flex: 1,
  },
  body: {
    flex: 1,
  },
  scrollContent: {
    paddingHorizontal: 24,
    paddingBottom: 180,
  },
  loadingState: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 12,
    paddingHorizontal: 24,
    paddingVertical: 8,
  },
  loadingLabel: {
    fontSize: 13,
    color: 'rgba(255, 255, 255, 0.7)',
  },
  errorBanner: {
    marginHorizontal: 24,
    marginTop: 8,
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderRadius: 16,
    backgroundColor: 'rgba(255, 94, 94, 0.12)',
    borderWidth: 1,
    borderColor: 'rgba(255, 94, 94, 0.3)',
  },
  errorText: {
    color: '#FF8A8A',
    fontSize: 13,
    fontWeight: '600',
    marginBottom: 8,
  },
  retryButton: {
    backgroundColor: 'rgba(255, 94, 94, 0.2)',
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 12,
    alignSelf: 'flex-start',
  },
  retryLabel: {
    color: '#FF8A8A',
    fontSize: 13,
    fontWeight: '700',
  },
  headerBar: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 24,
    paddingTop: 8,
    paddingBottom: 8,
    gap: 12,
  },
  headerTitle: {
    flex: 1,
    textAlign: 'center',
    fontSize: 18,
    fontWeight: '600',
    color: '#FFFFFF',
    letterSpacing: 0.4,
  },
  headerPlaceholder: {
    width: 48,
    height: 48,
  },
  topCarousel: {
    marginTop: 12,
    paddingVertical: 8,
    borderRadius: 22,
    backgroundColor: 'rgba(255, 255, 255, 0.04)',
  },
  emptyCarousel: {
    alignItems: 'center',
    justifyContent: 'center',
    height: 80,
  },
  emptyCarouselText: {
    color: 'rgba(255, 255, 255, 0.6)',
    fontSize: 13,
  },
  carouselContent: {
    paddingHorizontal: 12,
    alignItems: 'center',
    gap: 12,
  },
  previewFrame: {
    width: 56,
    height: 56,
    borderRadius: 18,
    borderWidth: 1,
    overflow: 'hidden',
    backgroundColor: 'rgba(255, 255, 255, 0.08)',
  },
  previewFrameActive: {
    transform: [{ scale: 1.05 }],
  },
  previewImage: {
    width: '100%',
    height: '100%',
  },
  heroStage: {
    marginTop: 32,
    borderRadius: 36,
    backgroundColor: '#111111',
    overflow: 'hidden',
    shadowColor: '#000000',
    shadowOpacity: 0.45,
    shadowRadius: 32,
    shadowOffset: { width: 0, height: 18 },
    elevation: 24,
  },
  heroImage: {
    width: '100%',
    height: 456,
    borderRadius: 36,
  },
  bottomInfoRow: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 16,
    marginTop: 32,
  },
  infoCard: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 16,
    paddingVertical: 12,
    borderRadius: 24,
    backgroundColor: 'rgba(255, 255, 255, 0.08)',
    gap: 12,
  },
  infoThumbnail: {
    width: 32,
    height: 32,
    borderRadius: 10,
    marginRight: 0,
  },
  infoTitle: {
    fontSize: 14,
    fontWeight: '600',
    color: '#FFFFFF',
    flex: 1,
    flexShrink: 1,
  },
  generateButton: {
    width: '100%',
    height: 56,
    borderRadius: 28,
    backgroundColor: '#D1FF00',
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
    gap: 10,
    marginTop: 18,
  },
  generateButtonDisabled: {
    opacity: 0.6,
  },
  generateLabel: {
    fontSize: 16,
    fontWeight: '700',
    color: '#050505',
    letterSpacing: 0.3,
  },
  menuTrigger: {
    width: 56,
    height: 56,
    borderRadius: 28,
    backgroundColor: 'rgba(255, 255, 255, 0.08)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  menuDots: {
    justifyContent: 'space-between',
    height: 24,
  },
  dot: {
    width: 6,
    height: 6,
    borderRadius: 3,
    backgroundColor: '#FFFFFF',
  },
  dotMiddle: {
    opacity: 0.7,
  },
  menuPanel: {
    position: 'absolute',
    right: 24,
    bottom: 200,
    zIndex: 50,
    elevation: 24,
    paddingVertical: 12,
    paddingHorizontal: 16,
    borderRadius: 20,
    backgroundColor: 'rgba(10, 10, 10, 0.94)',
    borderWidth: 1,
    borderColor: 'rgba(255, 255, 255, 0.08)',
    gap: 12,
  },
  menuItem: {
    paddingVertical: 4,
  },
  menuLabel: {
    fontSize: 15,
    fontWeight: '600',
    color: '#FFFFFF',
  },
});
