import * as React from 'react';
import { Upload, X, FileIcon, AlertCircle } from 'lucide-react';
import { cn } from '../../shared/utils';
import { Button } from '../button';
import { useFileUpload } from './use-file-upload';

interface FileUploadProps extends Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'onChange' | 'onError'
> {
  onFilesChange?: (files: File[]) => void;
  maxFiles?: number;
  maxSize?: number; // in bytes
  showPreview?: boolean;
  /** Called when files are rejected due to size or count limits. */
  onError?: (rejectedFiles: File[], reason: 'size' | 'count') => void;
}

/**
 * Drag-and-drop file input with preview list.
 *
 * @description
 * Manages selected file state and provides a standardized, accessible interface
 * for file uploads. Supports click-to-browse and drag-and-drop. Shows a preview
 * list of selected files with per-file remove buttons.
 *
 * Headless logic is available via `useFileUpload` for custom drop-zone UIs.
 *
 * @ai-rules
 * 1. Use `onFilesChange` to capture the selected files array in your form state.
 * 2. `maxFiles` defaults to 1 (single file). Set to a higher number for multi-upload.
 * 3. `maxSize` is in bytes (default: 5MB). Files exceeding the limit trigger `onError` and show an inline error.
 * 4. Set `showPreview={false}` if you manage the file list externally.
 * 5. Use `onError` to handle rejected files (e.g., show a toast notification).
 */
const FileUpload = React.forwardRef<HTMLDivElement, FileUploadProps>(
  (
    {
      className,
      onFilesChange,
      maxFiles = 1,
      maxSize = 5 * 1024 * 1024, // 5MB default
      showPreview = true,
      onError,
      accept,
      disabled,
      ...props
    },
    ref
  ) => {
    const {
      files,
      dragActive,
      errorMessage,
      inputRef,
      handleDrag,
      handleDrop,
      handleChange,
      removeFile,
      openFileDialog,
    } = useFileUpload({ maxFiles, maxSize, onFilesChange, onError, disabled });

    return (
      <div ref={ref} className={cn('w-full', className)}>
        <div
          onDragEnter={handleDrag}
          onDragLeave={handleDrag}
          onDragOver={handleDrag}
          onDrop={handleDrop}
          onClick={openFileDialog}
          className={cn(
            'relative flex cursor-pointer flex-col items-center justify-center rounded-[var(--radius)] border-2 border-dashed border-border bg-background p-8 transition-colors hover:bg-muted/50',
            dragActive && 'border-primary bg-primary/5',
            errorMessage && 'border-destructive/50',
            disabled && 'cursor-not-allowed opacity-50'
          )}
        >
          <Upload className="mb-4 h-10 w-10 text-muted-foreground" />
          <p className="mb-2 text-foreground">
            <span className="text-primary">Click to upload</span> or drag and drop
          </p>
          <p className="text-muted-foreground">
            {maxFiles > 1 ? `Up to ${maxFiles} files` : '1 file'} • Max{' '}
            {(maxSize / 1024 / 1024).toFixed(0)}MB
          </p>
          <input
            {...props}
            ref={inputRef}
            type="file"
            className="hidden"
            onChange={handleChange}
            multiple={maxFiles > 1}
            accept={accept}
            disabled={disabled}
          />
        </div>

        {errorMessage && (
          <div className="mt-2 flex items-center gap-2 rounded-[var(--radius)] border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive">
            <AlertCircle className="h-4 w-4 shrink-0" />
            <span>{errorMessage}</span>
          </div>
        )}

        {showPreview && files.length > 0 && (
          <div className="mt-4 space-y-2">
            {files.map((file, index) => (
              <div
                key={index}
                className="flex items-center justify-between rounded-[var(--radius)] border border-border bg-card p-3"
              >
                <div className="flex items-center gap-3">
                  <FileIcon className="h-5 w-5 text-muted-foreground" />
                  <div>
                    <p className="text-foreground">{file.name}</p>
                    <p className="text-muted-foreground">{(file.size / 1024).toFixed(2)} KB</p>
                  </div>
                </div>
                <Button
                  type="button"
                  variant="ghost"
                  size="sm"
                  onClick={e => {
                    e.stopPropagation();
                    removeFile(index);
                  }}
                  disabled={disabled}
                >
                  <X className="h-4 w-4" />
                </Button>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }
);
FileUpload.displayName = 'FileUpload';

export { FileUpload };
export type { FileUploadProps };
