import React, {useState} from 'react';
import {Pressable, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {
  IconAlertTriangle,
  IconCheck,
  IconDownload,
  IconExchange,
  IconFile,
  IconTrash,
} from '@tabler/icons-react-native';
import {Avatar} from '@components/_HuGo/Avatar';
import {getFileIcon} from '@components/_custom/FileList/utils';
import {
  CloseButton,
  IconButton,
  IconButtonProps,
} from '@components/_HuGo/Button';
import {CardContainer} from '@components/_HuGo/CardContainer';
import {Title} from '@components/_HuGo/Title';
import {ProgressBar} from '@components/_HuGo/ProgressBar';
import {Spinner} from '@components/_HuGo/Spinner';
import {tokenManager} from '@config/tokens';
import {getApiHeaders} from '@config/api';
import {commonStyles} from '@shared/styles';
import {useTheme} from '@shared/theme';
import {
  bytesToSize,
  getFileNameExtension,
  onDownloadFile,
  saveFileToDevice,
} from '@shared/utils';

import {FileCardProps} from './interfaces';
import {styles} from './styles';

const getAvatarIcon = ({
  isUploading,
  hasError,
  Icon,
  showCheckIcon,
  fileTypeIcon,
}: {
  isUploading?: boolean;
  hasError?: boolean;
  Icon?: FileCardProps['Icon'];
  showCheckIcon?: boolean;
  fileTypeIcon: FileCardProps['Icon'];
}): FileCardProps['Icon'] => {
  if (isUploading) {
    return IconFile;
  }
  if (hasError) {
    return IconAlertTriangle;
  }
  if (Icon) {
    return Icon;
  }
  if (showCheckIcon) {
    return IconCheck;
  }
  return fileTypeIcon;
};

interface FileInfoProps {
  children: React.ReactNode;
  isPressable: boolean;
  onPress?: () => void;
}

function FileInfo({children, isPressable, onPress}: FileInfoProps) {
  if (isPressable) {
    return (
      <Pressable style={styles.fileInformation} onPress={onPress}>
        {children}
      </Pressable>
    );
  }
  return <View style={styles.fileInformation}>{children}</View>;
}

export function FileCard({
  canDownloadFile = true,
  downloadWithAuthHeader,
  hasAvatar = true,
  hasError,
  id,
  isUploading,
  mime,
  name,
  onDeleteFile,
  onRetryUpload,
  onStopUpload,
  size,
  showCheckIcon = true,
  showFileTypeIcon = false,
  url,
  Icon,
  onPress,
  useSystemDownload = false,
}: FileCardProps) {
  const [isDownloading, setIsDownloading] = useState(false);
  const {theme} = useTheme();
  const {t} = useTranslation();

  const extension = getFileNameExtension(name ?? '', true);
  const fileTypeAvatar = showFileTypeIcon ? getFileIcon(extension) : undefined;
  const fileTypeIcon = fileTypeAvatar?.Icon ?? IconFile;
  const useFileTypeStyle =
    !!fileTypeAvatar && !hasError && !isUploading && !showCheckIcon && !Icon;

  const AvatarIcon = getAvatarIcon({
    isUploading,
    hasError,
    Icon,
    showCheckIcon,
    fileTypeIcon,
  });
  const iconCommonProps: Omit<IconButtonProps, 'Icon'> = {
    iconColor: theme.text.neutral.default,
    variant: 'tertiary',
  };
  const sizeText = size ? `${bytesToSize(size, 0)} • ` : '';

  const onPressDownload = async () => {
    if (!url) {
      return;
    }
    const headers = downloadWithAuthHeader
      ? getApiHeaders(tokenManager.getAccessToken())
      : undefined;
    setIsDownloading(true);
    try {
      if (useSystemDownload) {
        await saveFileToDevice({
          url,
          name: name ?? undefined,
          headers,
          mime,
        });
      } else {
        await onDownloadFile(name ?? '', url, {saveLocalFile: true, headers});
      }
    } finally {
      setIsDownloading(false);
    }
  };
  const onPressStop = () => onStopUpload?.(id);
  const onPressRetry = () => onRetryUpload?.(id);
  const onPressDelete = () => onDeleteFile?.(id);

  return (
    <CardContainer
      style={[
        styles.container,
        hasError && {
          backgroundColor: theme.background.feedback.error,
          borderColor: theme.border.states.error,
        },
      ]}>
      <View style={styles.fileContainer}>
        <FileInfo isPressable={!!onPress && !isUploading} onPress={onPress}>
          {hasAvatar && (
            <Avatar
              Icon={AvatarIcon}
              size="md"
              {...(useFileTypeStyle
                ? {variant: fileTypeAvatar!.variant}
                : {
                    iconColor: hasError
                      ? theme.text.feedback.error
                      : theme.text.neutral.brand,
                    style: {
                      backgroundColor: hasError
                        ? theme.background.feedback.error
                        : theme.background.layout.brand,
                    },
                  })}
            />
          )}
          <Title
            title={name}
            description={
              hasError
                ? t('general.upload_error')
                : `${sizeText}${
                    isUploading ? t('general.upload_loading') : extension
                  }`
            }
            size="s"
            style={commonStyles.flex}
          />
        </FileInfo>
        {isUploading ? (
          <>{onStopUpload && <CloseButton onPress={onPressStop} size="lg" />}</>
        ) : (
          <View style={styles.iconsContainer}>
            {hasError ? (
              <>
                {onRetryUpload && (
                  <IconButton
                    {...iconCommonProps}
                    Icon={IconExchange}
                    onPress={onPressRetry}
                  />
                )}
              </>
            ) : canDownloadFile && url ? (
              isDownloading ? (
                <View style={styles.spinner}>
                  <Spinner />
                </View>
              ) : (
                <IconButton
                  {...iconCommonProps}
                  Icon={IconDownload}
                  onPress={onPressDownload}
                />
              )
            ) : null}
            {onDeleteFile && (
              <IconButton
                {...iconCommonProps}
                Icon={IconTrash}
                onPress={onPressDelete}
              />
            )}
          </View>
        )}
      </View>
      {isUploading && <ProgressBar indeterminate />}
    </CardContainer>
  );
}

export * from './interfaces';
