import React from 'react';
import { ActivityIndicator, Image, Pressable, Text, View } from 'react-native';
import {
  AlertTriangle,
  File as FileIcon,
  FileImage,
  FileSpreadsheet,
  FileText,
  FileType as FileTypeGlyph,
  Presentation,
  Video,
  type LucideIcon,
} from 'lucide-react-native';

import { FILE_ATTACHMENT_SIZE, fileAttachmentStyles } from './fileAttachmentStyles';
import type { FileType } from './mediaUtils';

// File-type glyph + accent color, mirroring the web DS `FileAttachment`
// (`file-icons.tsx` FILE_TYPE_ICON_MAP → `--sem-file-icon-*`). The accent hexes
// are brand-fixed and identical in light/dark, exactly like the web tokens, so
// they're inlined here rather than routed through the theme mapper; `upload`
// stays a neutral muted foreground.
const FILE_TYPE_ICON: Record<FileType, { Icon: LucideIcon; color: string }> = {
  pdf: { Icon: FileText, color: '#DF3336' },
  image: { Icon: FileImage, color: '#F0ABFC' },
  slides: { Icon: Presentation, color: '#DDB440' },
  spreadsheet: { Icon: FileSpreadsheet, color: '#347043' },
  docs: { Icon: FileTypeGlyph, color: '#3B51E5' },
  video: { Icon: Video, color: '#7E73F2' },
  upload: { Icon: FileIcon, color: '#A1A1AA' },
};

export type FileAttachmentVariant = 'file' | 'image';
export type FileAttachmentSize = 'medium' | 'small';
export type FileAttachmentState = 'default' | 'loading' | 'error';

export interface FileAttachmentProps {
  /** Layout treatment: a labelled chip (`file`) or a square image thumbnail (`image`). @default "file" */
  variant?: FileAttachmentVariant;
  /** Size variant. @default "medium" */
  attachmentSize?: FileAttachmentSize;
  /** Attachment state — default, loading (uploading), or error (failed). @default "default" */
  state?: FileAttachmentState;
  /** File type — determines the leading icon in the `file` variant. @default "upload" */
  fileType?: FileType;
  /** File name shown in the chip (and used as the image `alt`/accessibility label). */
  name?: string;
  /** Image source URL for the `image` variant. */
  src?: string;
  /** Whether the remove (×) button is shown. @default false */
  removable?: boolean;
  /** Called when the remove button is pressed. */
  onRemove?: () => void;
  /** Accessibility label for the remove button. @default `Remove ${name}` */
  removeAriaLabel?: string;
  /** Called when the `file` chip itself is pressed (e.g. to open the file). Makes the chip tappable. */
  onPress?: () => void;
}

// A remove (×) badge straddling the top-right corner — identical for every
// attachment type (image thumbnail or file chip).
function RemoveButton({ label, onRemove }: { label: string; onRemove?: () => void }) {
  return (
    <Pressable
      accessibilityRole="button"
      accessibilityLabel={label}
      onPress={onRemove}
      style={[fileAttachmentStyles.removeButton, fileAttachmentStyles.removeButtonCorner]}
    >
      <Text style={fileAttachmentStyles.removeText}>×</Text>
    </Pressable>
  );
}

/**
 * An uploaded file shown as a labelled chip (`file`) or a square image
 * thumbnail (`image`) — the native mirror of the web DS `FileAttachment`.
 * Used in the composer's attachment strip and in sent chat messages.
 */
export function FileAttachment({
  variant = 'file',
  attachmentSize = 'medium',
  state = 'default',
  fileType = 'upload',
  name,
  src,
  removable = false,
  onRemove,
  removeAriaLabel,
  onPress,
}: FileAttachmentProps) {
  const sc = FILE_ATTACHMENT_SIZE[attachmentSize];
  const isError = state === 'error';
  const isLoading = state === 'loading';
  const label = removeAriaLabel ?? (name ? `Remove ${name}` : 'Remove attachment');
  const showRemove = removable && Boolean(onRemove);

  if (variant === 'image') {
    const imageEl = (
      <View style={[fileAttachmentStyles.imageContainer, { width: sc.image, height: sc.image }]}>
        <View style={[fileAttachmentStyles.imageWrap, isError && fileAttachmentStyles.errorBorder]}>
          {isLoading ? (
            <View style={fileAttachmentStyles.stateFill}>
              <ActivityIndicator />
            </View>
          ) : isError ? (
            <View style={fileAttachmentStyles.stateFill}>
              <AlertTriangle color="#DF3336" size={sc.icon} />
            </View>
          ) : src ? (
            <Image
              accessibilityLabel={name}
              source={{ uri: src }}
              style={fileAttachmentStyles.image}
            />
          ) : null}
        </View>
        {showRemove ? <RemoveButton label={label} onRemove={onRemove} /> : null}
      </View>
    );
    return showRemove ? <View style={fileAttachmentStyles.removeBadgePad}>{imageEl}</View> : imageEl;
  }

  const { Icon, color } = FILE_TYPE_ICON[fileType];
  const chipStyle = [fileAttachmentStyles.chip, isError && fileAttachmentStyles.errorBorder, { height: sc.chip }];
  const chipContent = (
    <>
      <View style={[fileAttachmentStyles.thumb, { height: sc.thumb, width: sc.thumb }]}>
        {isLoading ? (
          <ActivityIndicator />
        ) : isError ? (
          <AlertTriangle color="#DF3336" size={sc.icon} />
        ) : (
          <Icon color={color} size={sc.icon} />
        )}
      </View>
      {name ? (
        <Text numberOfLines={1} style={fileAttachmentStyles.chipName}>
          {name}
        </Text>
      ) : null}
      {showRemove ? <RemoveButton label={label} onRemove={onRemove} /> : null}
    </>
  );

  const chipEl = onPress ? (
    <Pressable
      accessibilityRole="button"
      accessibilityLabel={name ? `Open ${name}` : 'Open file'}
      onPress={onPress}
      style={chipStyle}
    >
      {chipContent}
    </Pressable>
  ) : (
    <View style={chipStyle}>{chipContent}</View>
  );
  return showRemove ? <View style={fileAttachmentStyles.removeBadgePad}>{chipEl}</View> : chipEl;
}
