import React, {useCallback, useMemo, useState} from 'react';
import {
  ScrollView,
  StyleProp,
  View,
  ViewStyle,
  useWindowDimensions,
} from 'react-native';
import {FileCard} from '@components/_HuGo/FileCard';
import {ImageModal} from '@components/_core/Image';
import {getIconByTypeOrExtension} from '@components/_custom/Attachment/constants';
import {PostAudioCard} from '@components/_custom/PostAudioCard';
import {useFullscreenVideo} from '@components/_custom/Video';
import {Attachment} from '@interfaces/attachments';
import {FILE_TYPES} from '@shared/constants';
import {SPACING} from '@shared/theme';
import {
  getFileNameExtension,
  handleFileView,
  isAndroid,
  isImage,
  isInlineAudioAttachment,
  isVideo,
} from '@shared/utils';

import {styles} from './styles';

const HEIC_MIMES = ['image/heic', 'image/heif'];

const isHeicAttachment = (item: Attachment): boolean => {
  if (item.mime && HEIC_MIMES.includes(item.mime.toLowerCase())) {
    return true;
  }
  const extension = getFileNameExtension(item.name ?? '', true);
  return extension === FILE_TYPES.HEIC || extension === FILE_TYPES.HEIF;
};

interface Props {
  files: Attachment[];
  style?: StyleProp<ViewStyle>;
}

export function FilesCarousel({files, style}: Props) {
  const hasFiles = !!files.length;
  const hasOneFile = files.length === 1;
  const {width: windowWidth} = useWindowDimensions();
  const audioSlideWidth = useMemo(
    () => windowWidth - SPACING.x4,
    [windowWidth],
  );
  const [previewImageUrl, setPreviewImageUrl] =
    useState<Nullable<string>>(null);
  const {openVideo, renderFullscreenVideo} = useFullscreenVideo();

  const closePreview = useCallback(() => {
    setPreviewImageUrl(null);
  }, []);

  const handleFilePress = useCallback(
    (item: Attachment) => {
      // Android can't decode HEIC inline; let the user pick a system app that can.
      if (isAndroid && isHeicAttachment(item)) {
        handleFileView({
          url: item.url,
          source: item.source,
          name: item.name,
          showOpenWithDialog: true,
        });
        return;
      }
      if (isImage(item) && item.url) {
        setPreviewImageUrl(item.url);
        return;
      }
      // Remote URLs don't play reliably in the system file viewer (iOS shows the
      // URL as text; Android often has no app for QuickTime/MOV). Stream via the
      // in-app player instead — ExoPlayer/AVPlayer handle common formats (.mov, .mp4).
      if (isVideo(item) && item.url) {
        openVideo(item.url);
        return;
      }
      handleFileView({
        url: item.url,
        source: item.source,
        name: item.name,
      });
    },
    [openVideo],
  );

  const renderFile = useCallback(
    (item: Attachment, index: number) => {
      const cardLayout = [
        styles.fileCard,
        hasOneFile ? styles.fullWidth : styles.partialWidth,
      ];
      const rowKey = `${item.id ?? item.url}-${index}`;

      if (isInlineAudioAttachment(item)) {
        return (
          <View
            key={rowKey}
            style={[
              styles.audioSlide,
              {width: audioSlideWidth, minWidth: audioSlideWidth},
            ]}>
            <PostAudioCard attachment={item} />
          </View>
        );
      }

      const extension = getFileNameExtension(item.name ?? '').toLowerCase();
      const Icon = getIconByTypeOrExtension(undefined, extension);
      const onPressItem = () => handleFilePress(item);

      return (
        <View key={rowKey} style={cardLayout}>
          <FileCard
            id={`${item.id}`}
            name={item.name ?? ''}
            mime={item.mime}
            path={item.url}
            url={item.url}
            size={item.bytes ?? 0}
            Icon={Icon}
            onPress={onPressItem}
            useSystemDownload
          />
        </View>
      );
    },
    [hasOneFile, handleFilePress, audioSlideWidth],
  );

  if (!hasFiles) {
    return null;
  }

  return (
    <>
      <ScrollView
        horizontal
        bounces={!hasOneFile}
        contentContainerStyle={[
          styles.filesContainer,
          hasOneFile && styles.fullWidth,
          style,
        ]}
        showsHorizontalScrollIndicator={false}>
        {files.map(renderFile)}
      </ScrollView>
      {!!previewImageUrl && (
        <ImageModal
          showZoom
          onClose={closePreview}
          source={{uri: previewImageUrl}}
        />
      )}
      {renderFullscreenVideo()}
    </>
  );
}
