import { FlashList } from '@shopify/flash-list';
import cn from 'classnames';
import Checkbox from 'expo-checkbox';
import React, { FC, ReactNode } from 'react';
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';

import { COLOR_SECONDARY } from '../../constants/custom';
import Title from '../List/components/Title';

type TableHeaderItem =
  | {
      title: string;
      classNames?: string;
    }
  | undefined;

type props = {
  items: string[][];
  title?: {
    text: string;
    icon?: {
      element: ReactNode;
      onPress: () => void;
    };
  };
  header?: TableHeaderItem[];
  footer?: ReactNode;
  emptyElement?: ReactNode;
  selected?: string[][];
  onSelect?: (value: boolean, item: string[]) => void;
  onSelectAll?: (value: boolean, items: string[][]) => void;
};

const TableRow = ({
  item,
  index,
  header,
  selected,
  onSelect,
}: {
  item: string[];
  index: number;
  header?: TableHeaderItem[];
  selected?: string[][];
  onSelect?: (value: boolean, item: string[]) => void;
}) => {
  const areArraysEqual = (arr1: string[], arr2: string[]) =>
    arr1.every((value, index) => value === arr2[index]);
  return (
    <View>
      {item && (
        <>
          {item && item.length && (
            <TouchableOpacity
              onPress={() =>
                onSelect &&
                onSelect(!selected?.some(value => areArraysEqual(value, item)) || false, item)
              }
              disabled={!onSelect}
              className={cn('flex-row justify-between rounded-sm p-2', {
                'bg-primary-bg': index % 2 === 0,
              })}
            >
              <View className="flex-row justify-between">
                {selected && onSelect && (
                  <Checkbox
                    className="mr-4"
                    value={selected?.some(value => areArraysEqual(value, item))}
                    onValueChange={value => onSelect(value, item)}
                    color={
                      selected?.some(value => areArraysEqual(value, item))
                        ? COLOR_SECONDARY
                        : undefined
                    }
                  />
                )}
                {item?.map((value, index) => (
                  <Text className={cn(header?.[index]?.classNames)} key={index}>
                    {value}
                  </Text>
                ))}
              </View>
            </TouchableOpacity>
          )}
        </>
      )}
    </View>
  );
};

const TableHeader = ({
  items,
  header,
  selected,
  onSelectAll,
}: {
  items: string[][];
  header?: TableHeaderItem[];
  selected?: string[][];
  onSelectAll?: (value: boolean, items: string[][]) => void;
}) => {
  return (
    <TouchableOpacity
      onPress={() =>
        onSelectAll && onSelectAll(items?.length !== selected?.length || false, items || [])
      }
      disabled={!onSelectAll}
      className="flex-row justify-between rounded-sm bg-primary p-2"
    >
      {selected && onSelectAll && (
        <Checkbox
          className="mr-4"
          value={items?.length === selected.length}
          onValueChange={value => onSelectAll(value, items || [])}
          color={items?.length === selected.length ? COLOR_SECONDARY : undefined}
        />
      )}
      {header?.map((value, index) => (
        <Text key={index} className={cn('text-white', value?.classNames)}>
          {value?.title}
        </Text>
      ))}
    </TouchableOpacity>
  );
};

const Table: FC<props> = ({
  items,
  title,
  header,
  footer,
  emptyElement,
  selected,
  onSelect,
  onSelectAll,
}) => {
  const fullHeight = items?.length > 20;
  return (
    <>
      {!items?.every(item => !item?.length) ? (
        <View className={cn({ 'flex-1': fullHeight }, 'mt-4')}>
          {title && <Title text={title.text} icons={title.icon ? [title.icon] : undefined} />}
          <View
            className={cn({ 'mt-4': title, 'flex-1': fullHeight }, 'rounded bg-secondary-bg p-2')}
          >
            {!fullHeight ? (
              <ScrollView>
                {header && (
                  <TableHeader
                    items={items}
                    header={header}
                    selected={selected}
                    onSelectAll={onSelectAll}
                  />
                )}
                {items?.map((item, index) => (
                  <TableRow
                    key={index}
                    item={item}
                    index={index}
                    header={header}
                    selected={selected}
                    onSelect={onSelect}
                  />
                ))}
                {footer && <View className="p-2">{footer}</View>}
              </ScrollView>
            ) : (
              <FlashList
                data={items}
                estimatedItemSize={50}
                keyExtractor={(item, index) => `${item}-${index}`}
                renderItem={({ item, index }) => (
                  <TableRow
                    item={item}
                    index={index}
                    header={header}
                    selected={selected}
                    onSelect={onSelect}
                  />
                )}
                ListHeaderComponent={
                  header ? (
                    <TableHeader
                      items={items}
                      header={header}
                      selected={selected}
                      onSelectAll={onSelectAll}
                    />
                  ) : undefined
                }
                ListFooterComponent={footer ? <View className="p-2">{footer}</View> : undefined}
              />
            )}
          </View>
        </View>
      ) : (
        <>
          {emptyElement && (
            <View className="mt-4">
              {title && <Title text={title.text} icons={title.icon ? [title.icon] : undefined} />}
              {emptyElement}
            </View>
          )}
        </>
      )}
    </>
  );
};

export default Table;
