/**
 * File grid for DMS file browser.
 * Displays files with icons, names, sizes, and action buttons.
 */

import React, { useMemo, useRef } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { useVirtualizer } from '@tanstack/react-virtual';
import type { DmsFile } from '@/api/dms';
import { Eye, FileText, Share2, Trash2 } from 'lucide-react';

import { getFileIcon, formatFileSize } from "./FileExplorer";

export interface FileGridProps {
  files: DmsFile[];
  selectedFileIds: Set<string>;
  onToggleSelect: (fileId: string) => void;
  onFileClick: (file: DmsFile) => void;
  onFileShare: (file: DmsFile) => void;
  onFileDelete: (file: DmsFile) => void;
  onFilePreview: (file: DmsFile) => void;
  loading?: boolean;
}

export function FileGrid({
  files,
  selectedFileIds,
  onToggleSelect,
  onFileClick,
  onFileShare,
  onFileDelete,
  onFilePreview,
  loading = false,
}: FileGridProps) {
  const { t } = useTranslation();
  const scrollRef = useRef<HTMLDivElement>(null);

  const sortedFiles = useMemo(() => {
    return [...files].sort((a, b) => a.name.localeCompare(b.name));
  }, [files]);

  const shouldVirtualize = sortedFiles.length >= 50;

  const rowVirtualizer = useVirtualizer({
    count: shouldVirtualize ? sortedFiles.length : 0,
    getScrollElement: () => scrollRef.current,
    estimateSize: () => 140,
    overscan: 8,
    enabled: shouldVirtualize,
  });

  if (loading) {
    return (
      <div className="grid gap-3 items-start content-start" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))' }} data-testid="file-grid-loading">
        {[1, 2, 3, 4, 5, 6].map((i) => (
          <div key={i} className="bg-white rounded-lg border border-secondary-200 p-4 animate-pulse">
            <div className="h-12 w-12 bg-secondary-100 rounded mb-3" />
            <div className="h-4 bg-secondary-100 rounded mb-2" />
            <div className="h-3 bg-secondary-50 rounded w-1/2" />
          </div>
        ))}
      </div>
    );
  }

  if (files.length === 0) {
    return (
      <div className="text-center py-12" data-testid="file-grid-empty">
        <FileText className="mx-auto h-12 w-12 text-secondary-300" aria-hidden="true" strokeWidth={1.5} />
        <p className="mt-2 text-sm text-secondary-500">{t('dms.noFiles')}</p>
      </div>
    );
  }

  return (
    <div
      ref={scrollRef}
      className="grid gap-3 items-start content-start overflow-y-auto h-full"
      style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))' }}
      data-testid="file-grid"
    >
      {shouldVirtualize ? (
        <div style={{ height: rowVirtualizer.getTotalSize(), position: 'relative', gridColumn: '1 / -1' }}>
          {rowVirtualizer.getVirtualItems().map((virtualRow) => {
            const file = sortedFiles[virtualRow.index];
            const icon = getFileIcon(file.mime_type);
            const isSelected = selectedFileIds.has(file.id);
            return (
              <div
                key={file.id}
                style={{
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  width: '100%',
                  transform: `translateY(${virtualRow.start}px)`,
                }}
              >
                <div
                  className={clsx(
                    'bg-white rounded-lg border p-3 motion-safe:transition-all cursor-pointer overflow-hidden flex flex-col',
                    isSelected ? 'border-primary-500 ring-2 ring-primary-200' : 'border-secondary-200 hover:border-secondary-300 hover:shadow-sm'
                  )}
                  onClick={() => onFileClick(file)}
                  data-testid={`file-card-${file.id}`}
                >
                  <div className="flex items-start justify-between mb-3">
                    <div className="flex items-center gap-2">
                      <input
                        type="checkbox"
                        checked={isSelected}
                        onChange={() => onToggleSelect(file.id)}
                        onClick={(e) => e.stopPropagation()}
                        className="rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
                        aria-label={t('dms.bulkSelect')}
                      />
                      <icon.icon className={clsx('w-10 h-10', icon.color)} aria-hidden="true" strokeWidth={1.5} />
                    </div>
                  </div>
                  <p className="text-sm font-medium text-secondary-900 truncate" title={file.name}>{file.name}</p>
                  <div className="mt-1 flex items-center gap-3 text-xs text-secondary-500">
                    <span>{formatFileSize(file.size_bytes ?? file.size ?? 0)}</span>
                    {file.mime_type && <span className="truncate">{file.mime_type.split('/')[1]?.toUpperCase()}</span>}
                  </div>
                  <div className="mt-3 flex items-center gap-1">
                    <button
                      onClick={(e) => { e.stopPropagation(); onFilePreview(file); }}
                      className="p-1.5 rounded text-secondary-400 hover:text-primary-600 hover:bg-primary-50 min-h-touch min-w-touch"
                      aria-label={t('dms.preview')}
                      title={t('dms.preview')}
                    >
                      <Eye className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                    </button>
                    <button
                      onClick={(e) => { e.stopPropagation(); onFileShare(file); }}
                      className="p-1.5 rounded text-secondary-400 hover:text-primary-600 hover:bg-primary-50 min-h-touch min-w-touch"
                      aria-label={t('dms.share')}
                      title={t('dms.share')}
                    >
                      <Share2 className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                    </button>
                    <button
                      onClick={(e) => { e.stopPropagation(); onFileDelete(file); }}
                      className="p-1.5 rounded text-secondary-400 hover:text-danger-600 hover:bg-danger-50 min-h-touch min-w-touch"
                      aria-label={t('dms.delete')}
                      title={t('dms.delete')}
                    >
                      <Trash2 className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                    </button>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      ) : (
        sortedFiles.map((file) => {
          const icon = getFileIcon(file.mime_type);
          const isSelected = selectedFileIds.has(file.id);
          return (
            <div
              key={file.id}
              className={clsx(
                'bg-white rounded-lg border p-3 motion-safe:transition-all cursor-pointer overflow-hidden flex flex-col',
                isSelected ? 'border-primary-500 ring-2 ring-primary-200' : 'border-secondary-200 hover:border-secondary-300 hover:shadow-sm'
              )}
              onClick={() => onFileClick(file)}
              data-testid={`file-card-${file.id}`}
            >
              <div className="flex items-start justify-between mb-3">
                <div className="flex items-center gap-2">
                  <input
                    type="checkbox"
                    checked={isSelected}
                    onChange={() => onToggleSelect(file.id)}
                    onClick={(e) => e.stopPropagation()}
                    className="rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
                    aria-label={t('dms.bulkSelect')}
                  />
                  <icon.icon className={clsx('w-10 h-10', icon.color)} aria-hidden="true" strokeWidth={1.5} />
                </div>
              </div>
              <p className="text-sm font-medium text-secondary-900 truncate" title={file.name}>{file.name}</p>
              <div className="mt-1 flex items-center gap-3 text-xs text-secondary-500">
                <span>{formatFileSize(file.size_bytes ?? file.size ?? 0)}</span>
                {file.mime_type && <span className="truncate">{file.mime_type.split('/')[1]?.toUpperCase()}</span>}
              </div>
              <div className="mt-3 flex items-center gap-1">
                <button
                  onClick={(e) => { e.stopPropagation(); onFilePreview(file); }}
                  className="p-1.5 rounded text-secondary-400 hover:text-primary-600 hover:bg-primary-50 min-h-touch min-w-touch"
                  aria-label={t('dms.preview')}
                  title={t('dms.preview')}
                >
                  <Eye className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                </button>
                <button
                  onClick={(e) => { e.stopPropagation(); onFileShare(file); }}
                  className="p-1.5 rounded text-secondary-400 hover:text-primary-600 hover:bg-primary-50 min-h-touch min-w-touch"
                  aria-label={t('dms.share')}
                  title={t('dms.share')}
                >
                  <Share2 className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                </button>
                <button
                  onClick={(e) => { e.stopPropagation(); onFileDelete(file); }}
                  className="p-1.5 rounded text-secondary-400 hover:text-danger-600 hover:bg-danger-50 min-h-touch min-w-touch"
                  aria-label={t('dms.delete')}
                  title={t('dms.delete')}
                >
                  <Trash2 className="w-4 h-4" aria-hidden="true" strokeWidth={2} />
                </button>
              </div>
            </div>
          );
        })
      )}
    </div>
  );
}
