import { Text } from './Text';
import { font, radius, spacing, useColors } from './styles';
import {
  Search,
  X,
  Smile,
  User,
  Cat,
  UtensilsCrossed,
  Plane,
  Gamepad2,
  Lightbulb,
  Hash,
  Flag,
} from 'lucide-react-native';
import React, { useRef, useState, useCallback, useMemo, useEffect } from 'react';
import {
  BackHandler,
  Modal,
  Pressable,
  ScrollView,
  StyleSheet,
  TextInput,
  View,
  Text as RNText,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useStrings } from '@/common/hooks/useStrings';
import type { Emoji } from 'emojibase';

const CATEGORY_IDS = [
  'smileys',
  'people',
  'animals',
  'food',
  'travel',
  'activities',
  'objects',
  'symbols',
  'flags',
] as const;

const CATEGORIES = [
  { group: 0, id: 'smileys' as const, icon: Smile },
  { group: 1, id: 'people' as const, icon: User },
  { group: 3, id: 'animals' as const, icon: Cat },
  { group: 4, id: 'food' as const, icon: UtensilsCrossed },
  { group: 5, id: 'travel' as const, icon: Plane },
  { group: 6, id: 'activities' as const, icon: Gamepad2 },
  { group: 7, id: 'objects' as const, icon: Lightbulb },
  { group: 8, id: 'symbols' as const, icon: Hash },
  { group: 9, id: 'flags' as const, icon: Flag },
] as const;

const SKIN_TONES = [
  { tone: undefined, color: '#FFCC4D' },
  { tone: 1, color: '#FADCBC' },
  { tone: 2, color: '#E0BB95' },
  { tone: 3, color: '#BF8F68' },
  { tone: 4, color: '#9B643D' },
  { tone: 5, color: '#594539' },
];

let cachedData: Emoji[] | null = null;
let cachedSections: { id: (typeof CATEGORY_IDS)[number]; emojis: Emoji[] }[] | null = null;

export function preloadIconData(): void {
  if (!cachedData) {
    cachedSections = null;
    import('emojibase-data/en/data.json').then(module => {
      cachedData = module.default as Emoji[];
      buildSections(cachedData);
    });
  }
}

async function loadEmojiData(): Promise<Emoji[]> {
  if (cachedData) return cachedData;
  const module = await import('emojibase-data/en/data.json');
  cachedData = module.default as Emoji[];
  return cachedData;
}

function shouldExclude(emoji: Emoji): boolean {
  if (emoji.group === 2) return true;
  const code = parseInt(emoji.hexcode.split('-')[0], 16);
  return code >= 0x1f1e6 && code <= 0x1f1ff;
}

function buildSections(data: Emoji[]): { id: (typeof CATEGORY_IDS)[number]; emojis: Emoji[] }[] {
  if (cachedSections) return cachedSections;
  const groups: Record<number, Emoji[]> = {};
  for (const emoji of data) {
    if (shouldExclude(emoji)) continue;
    const g = emoji.group ?? 0;
    if (!groups[g]) groups[g] = [];
    groups[g].push(emoji);
  }
  cachedSections = CATEGORIES.filter(c => c.group >= 0 && groups[c.group]?.length).map(c => ({
    id: c.id,
    emojis: groups[c.group],
  }));
  return cachedSections;
}

type Props = {
  visible: boolean;
  onClose: () => void;
  onSelect: (emoji: string) => void;
};

export function IconPicker({ visible, onClose, onSelect }: Props) {
  const c = useColors();
  const strings = useStrings();
  const insets = useSafeAreaInsets();
  const scrollRef = useRef<ScrollView>(null);
  const sectionOffsets = useRef<Record<string, number>>({});
  const isScrollingToSection = useRef(false);
  const [search, setSearch] = useState('');
  const [skinTone, setSkinTone] = useState<number | undefined>(undefined);
  const [showSkinPicker, setShowSkinPicker] = useState(false);
  const [sections, setSections] = useState<
    { id: (typeof CATEGORY_IDS)[number]; emojis: Emoji[] }[]
  >([]);
  const [ready, setReady] = useState(false);
  const [activeSection, setActiveSection] = useState<string | null>(null);

  useEffect(() => {
    if (visible && !ready) {
      loadEmojiData().then(data => {
        const built = buildSections(data);
        setSections(built);
        setReady(true);
        if (built.length > 0) setActiveSection(built[0].id);
      });
    }
  }, [visible, ready]);

  const [prevVisible, setPrevVisible] = useState(visible);
  if (visible !== prevVisible) {
    setPrevVisible(visible);
    if (!visible) {
      setSearch('');
      setShowSkinPicker(false);
    }
  }

  useEffect(() => {
    if (!visible) return;
    const handler = () => {
      onClose();
      return true;
    };
    const sub = BackHandler.addEventListener('hardwareBackPress', handler);
    return () => sub.remove();
  }, [visible, onClose]);

  const searchResults = useMemo(() => {
    if (!search.trim() || !cachedData) return null;
    const q = search.toLowerCase();
    return cachedData.filter(
      e =>
        !shouldExclude(e) &&
        (e.label.toLowerCase().includes(q) || e.tags?.some(t => t.toLowerCase().includes(q)))
    );
  }, [search]);

  const getEmojiWithSkin = useCallback(
    (emoji: Emoji): string => {
      if (!skinTone || !emoji.skins) return emoji.emoji;
      const skinned = emoji.skins.find(s => s.tone === skinTone);
      return skinned?.emoji ?? emoji.emoji;
    },
    [skinTone]
  );

  const handleSelect = useCallback(
    (emoji: Emoji) => {
      onSelect(getEmojiWithSkin(emoji));
    },
    [onSelect, getEmojiWithSkin]
  );

  const handleCategoryPress = useCallback((id: string) => {
    setActiveSection(id);
    const offset = sectionOffsets.current[id];
    if (offset !== undefined) {
      isScrollingToSection.current = true;
      scrollRef.current?.scrollTo({ y: offset, animated: true });
      setTimeout(() => {
        isScrollingToSection.current = false;
      }, 500);
    }
  }, []);

  const handleScroll = useCallback((e: { nativeEvent: { contentOffset: { y: number } } }) => {
    if (isScrollingToSection.current) return;
    const y = e.nativeEvent.contentOffset.y + 50;
    const ids = Object.keys(sectionOffsets.current);
    for (let i = ids.length - 1; i >= 0; i--) {
      if (sectionOffsets.current[ids[i]] <= y) {
        setActiveSection(ids[i]);
        return;
      }
    }
    if (ids.length > 0) setActiveSection(ids[0]);
  }, []);

  const handleSectionLayout = useCallback((id: string, y: number) => {
    sectionOffsets.current[id] = y;
  }, []);

  const renderEmojiGrid = (emojis: Emoji[]) => {
    const rows: Emoji[][] = [];
    for (let i = 0; i < emojis.length; i += 8) {
      rows.push(emojis.slice(i, i + 8));
    }
    return rows.map((row, rowIdx) => (
      <View key={rowIdx} style={styles.row}>
        {row.map(emoji => (
          <RNText key={emoji.hexcode} onPress={() => handleSelect(emoji)} style={styles.emojiBtn}>
            {getEmojiWithSkin(emoji)}
          </RNText>
        ))}
      </View>
    ));
  };

  return (
    <Modal visible={visible} animationType="slide">
      <View style={[styles.container, { backgroundColor: c.surface, paddingTop: insets.top }]}>
        <View style={styles.header}>
          <View style={[styles.searchBox, { backgroundColor: c.tagBg }]}>
            <Search size={18} color={c.tertiaryText} />
            <TextInput
              style={[styles.searchInput, { color: c.text }]}
              placeholder={strings.userCustomLogs.iconPicker.searchPlaceholder}
              placeholderTextColor={c.tertiaryText}
              value={search}
              onChangeText={setSearch}
              autoCorrect={false}
            />
            {search.length > 0 && (
              <Pressable onPress={() => setSearch('')} hitSlop={8}>
                <X size={16} color={c.tertiaryText} />
              </Pressable>
            )}
          </View>
          <Pressable
            onPress={() => setShowSkinPicker(!showSkinPicker)}
            style={[styles.skinBtn, { backgroundColor: c.tagBg }]}
          >
            <View
              style={[
                styles.skinDot,
                { backgroundColor: SKIN_TONES.find(s => s.tone === skinTone)?.color },
              ]}
            />
          </Pressable>
          <Pressable onPress={onClose} style={styles.closeBtn} hitSlop={12}>
            <X size={24} color={c.text} />
          </Pressable>
        </View>

        {showSkinPicker && (
          <View style={[styles.skinPicker, { backgroundColor: c.tagBg }]}>
            {SKIN_TONES.map(s => (
              <Pressable
                key={s.color}
                onPress={() => {
                  setSkinTone(s.tone);
                  setShowSkinPicker(false);
                }}
                style={[
                  styles.skinOption,
                  skinTone === s.tone && { backgroundColor: c.accent + '30' },
                ]}
              >
                <View style={[styles.skinDotLarge, { backgroundColor: s.color }]} />
              </Pressable>
            ))}
          </View>
        )}

        {!ready ? (
          <View style={styles.skeletonContainer}>
            {[0, 1, 2].map(section => (
              <View key={section}>
                <View style={[styles.skeletonHeader, { backgroundColor: c.tagBg }]} />
                {[0, 1, 2].map(row => (
                  <View key={row} style={styles.row}>
                    {[0, 1, 2, 3, 4, 5, 6, 7].map(cell => (
                      <View
                        key={cell}
                        style={[styles.skeletonCell, { backgroundColor: c.tagBg }]}
                      />
                    ))}
                  </View>
                ))}
              </View>
            ))}
          </View>
        ) : (
          <ScrollView
            ref={scrollRef}
            onScroll={handleScroll}
            scrollEventThrottle={100}
            keyboardShouldPersistTaps="handled"
            keyboardDismissMode="on-drag"
            showsVerticalScrollIndicator={false}
            contentContainerStyle={{ paddingHorizontal: 8, paddingBottom: 80 + insets.bottom }}
          >
            {searchResults ? (
              searchResults.length > 0 ? (
                <View>
                  <View style={styles.sectionHeader}>
                    <Text style={[styles.sectionTitle, { color: c.tertiaryText }]}>
                      {strings.userCustomLogs.iconPicker.results}
                    </Text>
                  </View>
                  {renderEmojiGrid(searchResults)}
                </View>
              ) : (
                <Text style={[styles.empty, { color: c.tertiaryText }]}>
                  {strings.userCustomLogs.iconPicker.noResults}
                </Text>
              )
            ) : (
              <>
                {sections.map(section => (
                  <View
                    key={section.id}
                    onLayout={e => handleSectionLayout(section.id, e.nativeEvent.layout.y)}
                  >
                    <View style={styles.sectionHeader}>
                      <Text style={[styles.sectionTitle, { color: c.tertiaryText }]}>
                        {strings.userCustomLogs.iconPicker.categories[section.id]}
                      </Text>
                    </View>
                    {renderEmojiGrid(section.emojis)}
                  </View>
                ))}
              </>
            )}
          </ScrollView>
        )}

        <View style={[styles.tabBar, { backgroundColor: c.surface, paddingBottom: insets.bottom }]}>
          <ScrollView
            horizontal
            showsHorizontalScrollIndicator={false}
            contentContainerStyle={styles.tabScroll}
          >
            {CATEGORIES.map(cat => {
              const Icon = cat.icon;
              const isActive = activeSection === cat.id;
              return (
                <Pressable
                  key={cat.id}
                  onPress={() => handleCategoryPress(cat.id)}
                  style={styles.tabBtn}
                >
                  <Icon size={20} color={isActive ? c.accent : c.tertiaryText} />
                </Pressable>
              );
            })}
          </ScrollView>
        </View>
      </View>
    </Modal>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 16,
    paddingVertical: 12,
    gap: 8,
  },
  searchBox: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    borderRadius: radius.md,
    paddingHorizontal: 12,
    height: 40,
    gap: 8,
  },
  searchInput: { flex: 1, fontSize: font.md, padding: 0 },
  skinBtn: {
    width: 40,
    height: 40,
    borderRadius: radius.md,
    alignItems: 'center',
    justifyContent: 'center',
  },
  skinDot: { width: 20, height: 20, borderRadius: 10 },
  closeBtn: { padding: 4 },
  skinPicker: {
    flexDirection: 'row',
    justifyContent: 'center',
    marginHorizontal: 16,
    marginBottom: 8,
    paddingVertical: 8,
    borderRadius: radius.md,
    gap: 8,
  },
  skinOption: { padding: 8, borderRadius: radius.sm },
  skinDotLarge: { width: 28, height: 28, borderRadius: 14 },
  skeletonContainer: { paddingHorizontal: 8, paddingTop: 8 },
  skeletonHeader: {
    width: 60,
    height: 12,
    borderRadius: 4,
    marginVertical: 8,
    marginHorizontal: 8,
  },
  skeletonCell: { flex: 1, height: 32, margin: 4, borderRadius: 8 },
  sectionHeader: { paddingVertical: 8, paddingHorizontal: 8 },
  sectionTitle: { fontSize: 12, fontWeight: '600', letterSpacing: 0.5, textTransform: 'uppercase' },
  row: { flexDirection: 'row', height: 44 },
  emojiBtn: {
    width: '12.5%',
    fontSize: 28,
    textAlign: 'center',
    textAlignVertical: 'center',
    lineHeight: 44,
  },
  empty: { textAlign: 'center', paddingVertical: spacing.xl, fontSize: font.md },
  tabBar: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    paddingTop: 8,
    borderTopWidth: StyleSheet.hairlineWidth,
    borderTopColor: 'rgba(128,128,128,0.2)',
  },
  tabScroll: { flexDirection: 'row', paddingHorizontal: 8, gap: 4 },
  tabBtn: { padding: 10, borderRadius: radius.md },
});
