import { MaterialCommunityIcons as Icon } from '@expo/vector-icons';
import React, { useEffect, useRef, useState } from 'react';
import {
  Animated,
  Dimensions,
  FlatList,
  Platform,
  StyleSheet,
  Text,
  TextInput,
  TextStyle,
  TouchableOpacity,
  View,
  ViewStyle,
} from 'react-native';
import Modal from 'react-native-modal';
import Colors from '../../constants/colors';
import Button from './lib/Button';
import TagItem from './lib/TagItem';
import utilities from './lib/utilities';

const { height } = Dimensions.get('window');
const INIT_HEIGHT = height * 0.6;

interface Option {
  id: string;
  name?: string;
  title?: string;
  form?: string;
  checked?: boolean;
}

interface Select2Props {
  data: Option[];
  style?: ViewStyle;
  modalStyle?: ViewStyle;
  title?: string;
  popupTitle?: string;
  colorTheme?: string;
  isSelectSingle?: boolean;
  cancelButtonText?: string;
  selectButtonText?: string;
  listEmptyTitle ?: string;
  searchPlaceHolderText?: string;
  showSearchBox?: boolean;
  selectedTitleStyle?: TextStyle;
  selectedPlaceholderTextColor?: TextStyle;
  buttonTextStyle?: TextStyle;
  buttonStyle?: ViewStyle;
  defaultFontName?: string;
  isEnable?: boolean;
  onSelect?: (selectedIds: string[], selectedItems: Option[]) => void;
  onRemoveItem?: (selectedIds: string[], selectedItems: Option[]) => void;
}

const Select2: React.FC<Select2Props> = ({
  data: propData,
  style,
  modalStyle,
  title,
  popupTitle,
  colorTheme = '#16a45f',
  isSelectSingle = false,
  cancelButtonText = 'Cancel',
  selectButtonText = 'Select',
  showSearchBox = true,
  selectedTitleStyle,
  selectedPlaceholderTextColor,
  buttonTextStyle,
  buttonStyle,
  defaultFontName,
  isEnable = true,
  onSelect,
  onRemoveItem,
}) => {
  const [show, setShow] = useState(false);
  const [selectedItem, setSelectedItem] = useState<Option[]>([]);
  const [preSelectedItem, setPreSelectedItem] = useState<Option[]>([]);
  const [data, setData] = useState<Option[]>(propData);
  const [keyword, setKeyword] = useState('');
  const animatedHeight = useRef(new Animated.Value(INIT_HEIGHT)).current;

  // Initialize preselected items
  useEffect(() => {
    const preSelected = propData.filter((item) => item.checked);
    setData(propData);
    setPreSelectedItem(preSelected);
  }, [propData]);

  const dataRender = data.filter((item) =>
    utilities
      .changeAlias(item.name || item.title || item.form || '')
      .includes(utilities.changeAlias(keyword))
  );

  const defaultFont: TextStyle = defaultFontName ? { fontFamily: defaultFontName } : {};

  const cancelSelection = () => {
    const resetData = data.map((item) => ({
      ...item,
      checked: preSelectedItem.some((pre) => pre.id === item.id),
    }));
    setData(resetData);
    setSelectedItem(preSelectedItem);
    setShow(false);
    setKeyword('');
  };

  const onItemSelected = (item: Option) => {
    let updatedData = [...data];
    const newItem = { ...item, checked: !item.checked };

    updatedData = updatedData.map((d) =>
      d.id === newItem.id ? newItem : isSelectSingle ? { ...d, checked: false } : d
    );

    const selectedItems = updatedData.filter((d) => d.checked);
    setData(updatedData);
    setSelectedItem(selectedItems);
  };

  const handleConfirmSelection = () => {
    const selectedIds = selectedItem.map((i) => i.id);
    onSelect && onSelect(selectedIds, selectedItem);
    setPreSelectedItem(selectedItem);
    setShow(false);
    setKeyword('');
  };

  const handleRemoveTag = (tag: Option) => {
    const updatedData = data.map((item) =>
      item.id === tag.id ? { ...item, checked: false } : item
    );
    const newSelected = updatedData.filter((d) => d.checked);
    setData(updatedData);
    setPreSelectedItem(newSelected);

    const selectedIds = newSelected.map((i) => i.id);
    onRemoveItem && onRemoveItem(selectedIds, newSelected);
  };

  const renderItem = ({ item }: { item: Option }) => (
    <TouchableOpacity
      onPress={() => onItemSelected(item)}
      activeOpacity={0.7}
      style={styles.itemWrapper}
    >
      <Text style={[styles.itemText, defaultFont]}>{item.name || item.form || item.title}</Text>
      <Icon
        style={styles.itemIcon}
        name={item.checked ? 'check-circle-outline' : 'radiobox-blank'}
        color={item.checked ? colorTheme : '#777777'}
        size={20}
      />
    </TouchableOpacity>
  );

  return (
    <TouchableOpacity
      onPress={isEnable ? () => setShow(true) : undefined}
      activeOpacity={0.7}
      style={[styles.container, style]}
    >
      <Modal
        onBackdropPress={() => setShow(false)}
        style={{ justifyContent: 'flex-end', margin: 0 }}
        useNativeDriver
        animationInTiming={300}
        animationOutTiming={300}
        hideModalContentWhileAnimating
        isVisible={show}
      >
        <Animated.View style={[styles.modalContainer, modalStyle, { height: animatedHeight }]}>
          <Text style={[styles.title, defaultFont, { color: colorTheme }]}>
            {popupTitle || title}
          </Text>
          <View style={styles.line} />
          {showSearchBox && (
            <TextInput
              style={[styles.inputKeyword, defaultFont]}
              placeholder="Search..."
              selectionColor={colorTheme}
              onChangeText={setKeyword}
              onFocus={() =>
                Animated.spring(animatedHeight, {
                  toValue: INIT_HEIGHT + (Platform.OS === 'ios' ? height * 0.2 : 0),
                  friction: 7,
                  useNativeDriver: false,
                }).start()
              }
              onBlur={() =>
                Animated.spring(animatedHeight, {
                  toValue: INIT_HEIGHT,
                  friction: 7,
                  useNativeDriver: false,
                }).start()
              }
            />
          )}
          <FlatList
            style={styles.listOption}
            data={dataRender.sort((a, b) => (a.name || '').localeCompare(b.name || ''))}
            keyExtractor={(item, index) => index.toString()}
            renderItem={renderItem}
            ListEmptyComponent={<Text style={[styles.empty, defaultFont]}>No options found</Text>}
          />
          <View style={styles.buttonWrapper}>
            <Button
              defaultFont={defaultFont}
              onPress={cancelSelection}
              title={cancelButtonText}
              textColor={colorTheme}
              backgroundColor="#fff"
              textStyle={buttonTextStyle}
              style={[styles.button, { marginRight: 5, marginLeft: 10, borderWidth: 1, borderColor: colorTheme }]}
            />
            <Button
              defaultFont={defaultFont}
              onPress={handleConfirmSelection}
              title={selectButtonText}
              backgroundColor={colorTheme}
              textStyle={buttonTextStyle}
              style={[styles.button, { marginLeft: 5, marginRight: 10 }]}
            />
          </View>
        </Animated.View>
      </Modal>

      {preSelectedItem.length > 0 ? (
        isSelectSingle ? (
          <View style={{ flexDirection: 'row', alignItems: 'center' }}>
            <Text style={[styles.selectedTitlte, defaultFont, selectedTitleStyle]}>
              {preSelectedItem[0].name || preSelectedItem[0].form || preSelectedItem[0].title}
            </Text>
            <Icon style={styles.itemIcon} name="chevron-down" color={Colors.colorPlaceholder} size={30} />
          </View>
        ) : (
          <View style={styles.tagWrapper}>
            {preSelectedItem.map((tag) => (
              <TagItem key={tag.id} tagName={tag.name || ''} onRemoveTag={() => handleRemoveTag(tag)} />
            ))}
          </View>
        )
      ) : (
        <View style={{ flexDirection: 'row', alignItems: 'center' }}>
          <Text style={[styles.selectedTitlte, defaultFont, selectedPlaceholderTextColor]}>{title}</Text>
          <Icon style={styles.itemIcon} name="chevron-down" color={Colors.colorPlaceholder} size={30} />
        </View>
      )}
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  container: {
    width: '100%',
    minHeight: 40,
    borderRadius: 2,
    paddingHorizontal: 16,
    flexDirection: 'row',
    alignItems: 'center',
    borderWidth: 1,
    paddingVertical: 4,
  },
  modalContainer: {
    paddingTop: 16,
    backgroundColor: '#fff',
    borderTopLeftRadius: 8,
    borderTopRightRadius: 8,
  },
  title: {
    fontSize: 16,
    marginBottom: 16,
    width: '100%',
    textAlign: 'center',
  },
  line: {
    height: 1,
    width: '100%',
    backgroundColor: '#cacaca',
  },
  inputKeyword: {
    height: 40,
    borderRadius: 5,
    borderWidth: 1,
    paddingLeft: 8,
    marginHorizontal: 24,
    marginTop: 16,
  },
  buttonWrapper: {
    marginVertical: 16,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  button: {
    height: 36,
    flex: 1,
  },
  selectedTitlte: {
    fontSize: 14,
    color: 'gray',
    flex: 1,
  },
  tagWrapper: {
    flexDirection: 'row',
    flexWrap: 'wrap',
  },
  listOption: {
    paddingHorizontal: 24,
    paddingTop: 1,
    marginTop: 16,
  },
  itemWrapper: {
    borderBottomWidth: 1,
    borderBottomColor: '#eaeaea',
    paddingVertical: 12,
    flexDirection: 'row',
    alignItems: 'center',
  },
  itemText: {
    fontSize: 16,
    color: '#333',
    flex: 1,
  },
  itemIcon: {
    width: 30,
    textAlign: 'right',
  },
  empty: {
    fontSize: 16,
    color: 'gray',
    alignSelf: 'center',
    textAlign: 'center',
    paddingTop: 16,
  },
});

export default Select2;