/**
 * FileExplorer - middle column file browser with multiple view modes.
 * Replaces FileGrid. Supports: list, table, icons-sm, icons-md, icons-lg.
 */

import React, { useMemo } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import type { DmsFile } from '@/api/dms';

export function getFileIcon(mimeType: string): { path: string; color: string } {
  if (mimeType === 'application/pdf') {
    return { path: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', color: 'text-danger-500' };
  }
  if (mimeType.startsWith('image/')) {
    return { path: 'M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z', color: 'text-accent-500' };
  }
  if (mimeType.includes('spreadsheet') || mimeType.includes('excel')) {
    return { path: 'M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', color: 'text-success-500' };
  }
  if (mimeType.includes('presentation') || mimeType.includes('powerpoint')) {
    return { path: 'M7 8h10M7 16h10M7 12h6m-7 8h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z', color: 'text-warning-500' };
  }
  if (mimeType.startsWith('text/') || mimeType.includes('document') || mimeType.includes('word')) {
    return { path: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', color: 'text-primary-500' };
  }
  if (mimeType.includes('zip') || mimeType.includes('compressed') || mimeType.includes('archive')) {
    return { path: 'M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4', color: 'text-secondary-500' };
  }
  return { path: 'M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z', color: 'text-secondary-400' };
}

export function formatFileSize(bytes: number): string {
  if (!bytes || bytes < 0) return '0 B';
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}

function getFileSize(file: DmsFile): number {
  return file.size_bytes ?? file.size ?? 0;
}

function formatDate(dateStr: string | null | undefined): string {
  if (!dateStr) return '';
  try {
    const d = new Date(dateStr);
    return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
  } catch {
    return dateStr;
  }
}

export type ViewMode = 'list' | 'table' | 'icons-sm' | 'icons-md' | 'icons-lg';
export type SortBy = 'name' | 'size' | 'date' | 'type';
export type SortOrder = 'asc' | 'desc';

export interface FileExplorerProps {
  files: DmsFile[];
  selectedFileIds: Set<string>;
  selectedFile: DmsFile | null;
  viewMode: ViewMode;
  onToggleSelect: (fileId: string) => void;
  onFileClick: (file: DmsFile) => void;
  onFileDoubleClick: (file: DmsFile) => void;
  onFileShare: (file: DmsFile) => void;
  onFileDelete: (file: DmsFile) => void;
  onFilePreview: (file: DmsFile) => void;
  loading?: boolean;
  sortBy: SortBy;
  sortOrder: SortOrder;
  onSortChange: (by: string, order: string) => void;
}

function SortHeader({
  label,
  field,
  sortBy,
  sortOrder,
  onSortChange,
  className,
}: {
  label: string;
  field: SortBy;
  sortBy: SortBy;
  sortOrder: SortOrder;
  onSortChange: (by: string, order: string) => void;
  className?: string;
}) {
  const isActive = sortBy === field;
  return (
    <button
      type="button"
      onClick={() => onSortChange(field, isActive && sortOrder === 'asc' ? 'desc' : 'asc')}
      className={clsx(
        'inline-flex items-center gap-1 text-xs font-medium hover:text-secondary-700',
        isActive ? 'text-primary-600' : 'text-secondary-500',
        className,
      )}
    >
      {label}
      {isActive && (
        <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={sortOrder === 'asc' ? 'M5 15l7-7 7 7' : 'M19 9l-7 7-7-7'} />
        </svg>
      )}
    </button>
  );
}

function ActionButtons({
  file,
  onFilePreview,
  onFileShare,
  onFileDelete,
  t,
}: {
  file: DmsFile;
  onFilePreview: (file: DmsFile) => void;
  onFileShare: (file: DmsFile) => void;
  onFileDelete: (file: DmsFile) => void;
  t: (key: string) => string;
}) {
  return (
    <div className="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')}
      >
        <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
        </svg>
      </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')}
      >
        <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.7 10.7l6.6-3.4M8.7 13.3l6.6 3.4M18 12a3 3 0 11-6 0 3 3 0 016 0zM9 12a3 3 0 11-6 0 3 3 0 016 0z" />
        </svg>
      </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')}
      >
        <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
        </svg>
      </button>
    </div>
  );
}

export function FileExplorer({
  files,
  selectedFileIds,
  selectedFile,
  viewMode,
  onToggleSelect,
  onFileClick,
  onFileDoubleClick,
  onFileShare,
  onFileDelete,
  onFilePreview,
  loading = false,
  sortBy,
  sortOrder,
  onSortChange,
}: FileExplorerProps) {
  const { t } = useTranslation();

  const sortedFiles = useMemo(() => {
    const sorted = [...files];
    sorted.sort((a, b) => {
      let cmp = 0;
      if (sortBy === 'name') {
        cmp = a.name.localeCompare(b.name);
      } else if (sortBy === 'size') {
        cmp = getFileSize(a) - getFileSize(b);
      } else if (sortBy === 'date') {
        cmp = (a.updated_at || a.created_at || '').localeCompare(b.updated_at || b.created_at || '');
      } else if (sortBy === 'type') {
        cmp = a.mime_type.localeCompare(b.mime_type);
      }
      return sortOrder === 'asc' ? cmp : -cmp;
    });
    return sorted;
  }, [files, sortBy, sortOrder]);

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12" data-testid="file-explorer-loading">
        <svg className="animate-spin h-6 w-6 text-secondary-400" fill="none" viewBox="0 0 24 24" aria-hidden="true">
          <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
          <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
        </svg>
        <span className="ml-2 text-secondary-500 text-sm">{t('dms.loading')}</span>
      </div>
    );
  }

  if (files.length === 0) {
    return (
      <div className="text-center py-12" data-testid="file-explorer-empty">
        <svg className="mx-auto h-12 w-12 text-secondary-300" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
        </svg>
        <p className="mt-2 text-sm text-secondary-500">{t('dms.noFiles')}</p>
      </div>
    );
  }

  // ─── List View ───
  if (viewMode === 'list') {
    return (
      <div className="overflow-y-auto h-full" data-testid="file-explorer-list">
        {/* Sort header */}
        <div className="flex items-center gap-2 px-3 py-2 border-b border-secondary-100 sticky top-0 bg-white z-10">
          <SortHeader label={t('dms.sortName')} field="name" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
          <span className="text-secondary-300">|</span>
          <SortHeader label={t('dms.sortSize')} field="size" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
          <span className="text-secondary-300">|</span>
          <SortHeader label={t('dms.sortDate')} field="date" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
        </div>
        <ul className="divide-y divide-secondary-50">
          {sortedFiles.map((file) => {
            const icon = getFileIcon(file.mime_type);
            const isSelected = selectedFileIds.has(file.id);
            const isActive = selectedFile?.id === file.id;
            return (
              <li key={file.id}>
                <div
                  className={clsx(
                    'flex items-center gap-2 px-3 py-2 cursor-pointer motion-safe:transition-colors',
                    isActive ? 'bg-primary-50' : 'hover:bg-secondary-50',
                  )}
                  onClick={() => onFileClick(file)}
                  onDoubleClick={() => onFileDoubleClick(file)}
                  data-testid={`file-row-${file.id}`}
                >
                  <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 flex-shrink-0"
                    aria-label={t('dms.bulkSelect')}
                  />
                  <svg className={clsx('w-5 h-5 flex-shrink-0', icon.color)} fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d={icon.path} />
                  </svg>
                  <span className="text-sm font-medium text-secondary-900 truncate flex-1" title={file.name}>{file.name}</span>
                  <span className="text-xs text-secondary-500 flex-shrink-0">{formatFileSize(getFileSize(file))}</span>
                  <span className="text-xs text-secondary-400 flex-shrink-0 hidden sm:inline">{formatDate(file.updated_at || file.created_at)}</span>
                  <ActionButtons file={file} onFilePreview={onFilePreview} onFileShare={onFileShare} onFileDelete={onFileDelete} t={t} />
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }

  // ─── Table View ───
  if (viewMode === 'table') {
    return (
      <div className="overflow-auto h-full" data-testid="file-explorer-table">
        <table className="w-full text-sm">
          <thead className="sticky top-0 bg-white border-b border-secondary-200 z-10">
            <tr>
              <th className="px-3 py-2 w-8">
                <input
                  type="checkbox"
                  className="rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
                  aria-label={t('dms.bulkSelect')}
                  onChange={() => {}}
                />
              </th>
              <th className="px-3 py-2 text-left">
                <SortHeader label={t('dms.sortName')} field="name" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
              </th>
              <th className="px-3 py-2 text-left">
                <SortHeader label={t('dms.fileSize')} field="size" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
              </th>
              <th className="px-3 py-2 text-left">
                <SortHeader label={t('dms.fileType')} field="type" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
              </th>
              <th className="px-3 py-2 text-left">
                <SortHeader label={t('dms.fileModified')} field="date" sortBy={sortBy} sortOrder={sortOrder} onSortChange={onSortChange} />
              </th>
              <th className="px-3 py-2 text-right">{t('common.actions')}</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-secondary-50">
            {sortedFiles.map((file) => {
              const icon = getFileIcon(file.mime_type);
              const isSelected = selectedFileIds.has(file.id);
              const isActive = selectedFile?.id === file.id;
              return (
                <tr
                  key={file.id}
                  className={clsx(
                    'cursor-pointer motion-safe:transition-colors',
                    isActive ? 'bg-primary-50' : 'hover:bg-secondary-50',
                  )}
                  onClick={() => onFileClick(file)}
                  onDoubleClick={() => onFileDoubleClick(file)}
                  data-testid={`file-row-${file.id}`}
                >
                  <td className="px-3 py-2" onClick={(e) => e.stopPropagation()}>
                    <input
                      type="checkbox"
                      checked={isSelected}
                      onChange={() => onToggleSelect(file.id)}
                      className="rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
                      aria-label={t('dms.bulkSelect')}
                    />
                  </td>
                  <td className="px-3 py-2">
                    <div className="flex items-center gap-2">
                      <svg className={clsx('w-5 h-5 flex-shrink-0', icon.color)} fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d={icon.path} />
                      </svg>
                      <span className="font-medium text-secondary-900 truncate" title={file.name}>{file.name}</span>
                    </div>
                  </td>
                  <td className="px-3 py-2 text-secondary-600">{formatFileSize(getFileSize(file))}</td>
                  <td className="px-3 py-2 text-secondary-600">{file.mime_type.split('/')[1]?.toUpperCase() || t('dms.icon.other')}</td>
                  <td className="px-3 py-2 text-secondary-600">{formatDate(file.updated_at || file.created_at)}</td>
                  <td className="px-3 py-2" onClick={(e) => e.stopPropagation()}>
                    <ActionButtons file={file} onFilePreview={onFilePreview} onFileShare={onFileShare} onFileDelete={onFileDelete} t={t} />
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }

  // ─── Icon Views ───
  const gridClass =
    viewMode === 'icons-sm'
      ? 'grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-8'
      : viewMode === 'icons-md'
        ? 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5'
        : 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3';

  const iconSize =
    viewMode === 'icons-sm' ? 'w-8 h-8'
      : viewMode === 'icons-md' ? 'w-10 h-10'
        : 'w-16 h-16';

  return (
    <div className={clsx('grid gap-3 p-3 overflow-y-auto h-full', gridClass)} data-testid={`file-explorer-${viewMode}`}>
      {sortedFiles.map((file) => {
        const icon = getFileIcon(file.mime_type);
        const isSelected = selectedFileIds.has(file.id);
        const isActive = selectedFile?.id === file.id;
        return (
          <div
            key={file.id}
            className={clsx(
              'bg-white rounded-lg border p-3 motion-safe:transition-all cursor-pointer flex flex-col items-center text-center',
              isActive
                ? 'border-primary-500 ring-2 ring-primary-200'
                : isSelected
                  ? 'border-primary-400'
                  : 'border-secondary-200 hover:border-secondary-300 hover:shadow-sm',
            )}
            onClick={() => onFileClick(file)}
            onDoubleClick={() => onFileDoubleClick(file)}
            data-testid={`file-card-${file.id}`}
          >
            <div className="flex items-center justify-between w-full mb-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')}
              />
            </div>
            {viewMode === 'icons-lg' && file.mime_type.startsWith('image/') ? (
              <div className="w-16 h-16 bg-secondary-100 rounded-lg flex items-center justify-center mb-2 overflow-hidden">
                <img
                  src={`/api/v1/dms/files/${file.id}/preview`}
                  alt={file.name}
                  className="w-full h-full object-cover"
                  onError={(e) => {
                    (e.target as HTMLImageElement).style.display = 'none';
                  }}
                />
              </div>
            ) : (
              <svg className={clsx(iconSize, icon.color, 'mb-2')} fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d={icon.path} />
              </svg>
            )}
            <p className="text-xs font-medium text-secondary-900 truncate w-full" title={file.name}>{file.name}</p>
            <div className="mt-1 flex items-center gap-2 text-xs text-secondary-500">
              <span>{formatFileSize(getFileSize(file))}</span>
            </div>
            <div className="mt-2">
              <ActionButtons file={file} onFilePreview={onFilePreview} onFileShare={onFileShare} onFileDelete={onFileDelete} t={t} />
            </div>
          </div>
        );
      })}
    </div>
  );
}
