/**
 * FilesPage
 *
 * Split-view file management: FolderTree on the left, FormGeneratorTable on the right.
 * Uses useResizablePanels for the divider.
 */

import React, { useState, useMemo, useEffect, useRef, useCallback } from 'react';
import api from '../../api';
import { useUserFiles, useFileOperations } from '../../hooks/useFiles';
import { useFileContext } from '../../contexts/FileContext';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm } from '../../components/FormGenerator/FormGeneratorForm';
import FolderTree from '../../components/FolderTree/FolderTree';
import type { FileNode } from '../../components/FolderTree/FolderTree';
import { useResizablePanels } from '../../hooks/useResizablePanels';
import { FaSync, FaFolder, FaUpload, FaDownload, FaEye, FaFolderPlus } from 'react-icons/fa';
import { useToast } from '../../contexts/ToastContext';
import styles from '../admin/Admin.module.css';

interface UserFile {
  id: string;
  fileName: string;
  mimeType?: string;
  fileSize?: number;
  folderId?: string | null;
  featureInstanceId?: string;
  [key: string]: any;
}

export const FilesPage: React.FC = () => {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const { showSuccess, showError } = useToast();
  const [selectedFolderId, setSelectedFolderId] = useState<string | null>(null);

  const {
    leftWidth, isDragging, handleMouseDown, containerRef,
  } = useResizablePanels({
    storageKey: 'filesPage-panelWidth',
    defaultLeftWidth: 22,
    minLeftWidth: 15,
    maxLeftWidth: 40,
  });

  const {
    data: files,
    attributes,
    permissions,
    loading,
    error,
    refetch,
    fetchFileById,
    updateFileOptimistically,
  } = useUserFiles();

  const {
    handleFileDownload,
    handleFileDelete,
    handleFileDeleteMultiple,
    handleFileUpload,
    handleFileUpdate,
    handleFilePreview,
    handleInlineUpdate,
    deletingFiles,
    downloadingFiles,
    uploadingFile,
    previewingFiles,
  } = useFileOperations();

  const {
    folders,
    refreshFolders,
    handleCreateFolder,
    handleRenameFolder,
    handleDeleteFolder,
    handleMoveFolder,
    handleMoveFolders,
    handleMoveFile,
    handleMoveFiles: contextMoveFiles,
    handleDownloadFolder,
    expandedFolderIds,
    toggleFolderExpanded,
  } = useFileContext();

  const [editingFile, setEditingFile] = useState<UserFile | null>(null);
  const [selectedFiles, setSelectedFiles] = useState<UserFile[]>([]);
  const [treeSelectedIds, setTreeSelectedIds] = useState<Set<string>>(new Set());
  const [highlightedFileId, setHighlightedFileId] = useState<string | null>(null);

  useEffect(() => { refetch(); }, []);

  const treeFileNodes: FileNode[] = useMemo(() => {
    if (!files) return [];
    return files.map((f: UserFile) => ({
      id: f.id,
      fileName: f.fileName,
      mimeType: f.mimeType,
      fileSize: f.fileSize,
      folderId: f.folderId ?? null,
    }));
  }, [files]);

  const _handleTreeFileSelect = useCallback((fileId: string) => {
    const file = files?.find((f: UserFile) => f.id === fileId);
    if (file) {
      setSelectedFolderId(file.folderId ?? null);
      setHighlightedFileId(fileId);
      requestAnimationFrame(() => {
        const row = document.querySelector('tr[data-highlighted="true"]');
        if (row) row.scrollIntoView({ behavior: 'smooth', block: 'center' });
      });
      setTimeout(() => setHighlightedFileId(null), 2500);
    }
  }, [files]);

  const filteredFiles = useMemo(() => {
    if (!files) return [];
    if (selectedFolderId === null) {
      return files.filter((f: UserFile) => !f.folderId);
    }
    return files.filter((f: UserFile) => f.folderId === selectedFolderId);
  }, [files, selectedFolderId]);

  const columns = useMemo(() => {
    const hiddenColumns = ['id', 'mandateId', 'fileHash', 'folderId'];

    const cols = (attributes || [])
      .filter(attr => !hiddenColumns.includes(attr.name))
      .map(attr => ({
        key: attr.name,
        label: attr.label || attr.name,
        type: attr.type as any,
        sortable: attr.sortable !== false,
        filterable: attr.filterable !== false,
        searchable: attr.searchable !== false,
        width: attr.width || 150,
        minWidth: attr.minWidth || 100,
        maxWidth: attr.maxWidth || 400,
        fkSource: (attr as any).fkSource,
        fkDisplayField: (attr as any).fkDisplayField,
      }));

    cols.push({
      key: '_createdBy',
      label: 'Created By',
      type: 'text' as any,
      sortable: true,
      filterable: false,
      searchable: false,
      width: 150,
      minWidth: 100,
      maxWidth: 250,
    } as any);

    return cols;
  }, [attributes]);

  const canCreate = permissions?.create !== 'n';
  const canUpdate = permissions?.update !== 'n';
  const canDelete = permissions?.delete !== 'n';

  const handleEditClick = async (file: UserFile) => {
    const fullFile = await fetchFileById(file.id);
    if (fullFile) setEditingFile(fullFile as UserFile);
  };

  const handleEditSubmit = async (data: Partial<UserFile>) => {
    if (!editingFile) return;
    const result = await handleFileUpdate(editingFile.id, {
      fileName: data.fileName || editingFile.fileName
    }, editingFile);
    if (result.success) {
      setEditingFile(null);
      refetch();
    }
  };

  const handleDelete = async (file: UserFile) => {
    const success = await handleFileDelete(file.id);
    if (success) refetch();
  };

  const handleDeleteMultiple = async (filesToDelete: UserFile[]) => {
    const ids = filesToDelete.map(f => f.id);
    const success = await handleFileDeleteMultiple(ids);
    if (success) refetch();
  };

  const handleDownload = async (file: UserFile) => {
    await handleFileDownload(file.id, file.fileName);
  };

  const handlePreview = async (file: UserFile) => {
    const result = await handleFilePreview(file.id, file.fileName, file.mimeType);
    if (result.success && result.previewUrl) {
      window.open(result.previewUrl, '_blank');
    }
  };

  const handleUploadClick = () => { fileInputRef.current?.click(); };

  const handleFileSelect = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFiles = e.target.files;
    if (selectedFiles && selectedFiles.length > 0) {
      let successCount = 0;
      let errorCount = 0;
      for (const file of Array.from(selectedFiles)) {
        const result = await handleFileUpload(file);
        if (result?.success) successCount++; else errorCount++;
      }
      if (fileInputRef.current) fileInputRef.current.value = '';
      await refetch();
      if (successCount > 0) {
        showSuccess(
          'Upload erfolgreich',
          `${successCount} Datei(en) hochgeladen${errorCount > 0 ? `, ${errorCount} fehlgeschlagen` : ''}`
        );
      } else if (errorCount > 0) {
        showError('Upload fehlgeschlagen', `${errorCount} Datei(en) konnten nicht hochgeladen werden`);
      }
    }
  };

  const _handleNewFolder = useCallback(async () => {
    const name = prompt('Neuer Ordnername:');
    if (name?.trim()) {
      await handleCreateFolder(name.trim(), selectedFolderId);
    }
  }, [handleCreateFolder, selectedFolderId]);

  const _onRowDragStart = useCallback((e: React.DragEvent<HTMLTableRowElement>, row: UserFile) => {
    const isInSelection = selectedFiles.some(f => f.id === row.id);
    if (isInSelection && selectedFiles.length > 1) {
      const ids = selectedFiles.map(f => f.id);
      e.dataTransfer.setData('application/file-ids', JSON.stringify(ids));
    } else {
      e.dataTransfer.setData('application/file-id', row.id);
    }
    e.dataTransfer.effectAllowed = 'move';
  }, [selectedFiles]);

  const _handleMoveFilePage = useCallback(async (fileId: string, targetFolderId: string | null) => {
    await handleMoveFile(fileId, targetFolderId);
    await refetch();
  }, [handleMoveFile, refetch]);

  const _handleMoveFiles = useCallback(async (fileIds: string[], targetFolderId: string | null) => {
    await contextMoveFiles(fileIds, targetFolderId);
    await refetch();
  }, [contextMoveFiles, refetch]);

  const _handleRenameFile = useCallback(async (fileId: string, newName: string) => {
    await handleFileUpdate(fileId, { fileName: newName });
    await refetch();
  }, [handleFileUpdate, refetch]);

  const _handleDeleteTreeFile = useCallback(async (fileId: string) => {
    await handleFileDelete(fileId);
    await refetch();
  }, [handleFileDelete, refetch]);

  const _handleDeleteTreeFiles = useCallback(async (fileIds: string[]) => {
    await handleFileDeleteMultiple(fileIds);
    await refetch();
  }, [handleFileDeleteMultiple, refetch]);

  const _handleDeleteTreeFolders = useCallback(async (folderIds: string[]) => {
    await api.post('/api/files/batch-delete', { folderIds, recursiveFolders: true });
    await refreshFolders();
    await refetch();
  }, [refreshFolders, refetch]);

  const _handleTreeRefresh = useCallback(async () => {
    await refetch();
    await refreshFolders();
  }, [refetch, refreshFolders]);

  const _tableRefetch = useCallback(async (params?: any) => {
    const nextParams = { ...(params || {}) };
    const nextFilters = { ...(nextParams.filters || {}) };
    nextFilters.folderId = selectedFolderId;
    nextParams.filters = nextFilters;
    await refetch(nextParams);
  }, [refetch, selectedFolderId]);

  useEffect(() => {
    _tableRefetch({ page: 1, pageSize: 25 });
  }, [selectedFolderId, _tableRefetch]);

  const formAttributes = useMemo(() => {
    const excludedFields = ['id', 'mandateId', 'fileHash', '_createdBy', '_createdAt', '_modifiedAt', 'creationDate', 'source'];
    return (attributes || []).filter(attr => !excludedFields.includes(attr.name));
  }, [attributes]);

  if (error) {
    return (
      <div className={styles.adminPage}>
        <div className={styles.errorContainer}>
          <span className={styles.errorIcon}>⚠️</span>
          <p className={styles.errorMessage}>Fehler beim Laden der Dateien: {error}</p>
          <button className={styles.secondaryButton} onClick={() => refetch()}>
            <FaSync /> Erneut versuchen
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className={`${styles.adminPage} ${styles.adminPageFill}`}>
      <input
        ref={fileInputRef}
        type="file"
        multiple
        style={{ display: 'none' }}
        onChange={handleFileSelect}
      />

      <div className={styles.pageHeader}>
        <div>
          <h1 className={styles.pageTitle}>Dateien</h1>
          <p className={styles.pageSubtitle}>Dateiverwaltung</p>
        </div>
        <div className={styles.headerActions}>
          <button className={styles.secondaryButton} onClick={() => { refetch(); refreshFolders(); }} disabled={loading}>
            <FaSync className={loading ? 'spinning' : ''} /> Aktualisieren
          </button>
        </div>
      </div>

      {/* Split-view container */}
      <div
        ref={containerRef as React.RefObject<HTMLDivElement>}
        style={{ display: 'flex', flex: 1, overflow: 'hidden', minHeight: 0, position: 'relative' }}
      >
        {/* Left panel: FolderTree */}
        <div style={{
          width: `${leftWidth}%`,
          minWidth: 0,
          overflow: 'auto',
          borderRight: '1px solid var(--color-border, #e0e0e0)',
          padding: '8px 4px',
        }}>
          <FolderTree
            folders={folders}
            files={treeFileNodes}
            showFiles={true}
            selectedFolderId={selectedFolderId}
            onSelect={setSelectedFolderId}
            onFileSelect={_handleTreeFileSelect}
            selectedItemIds={treeSelectedIds}
            onSelectionChange={setTreeSelectedIds}
            expandedIds={expandedFolderIds}
            onToggleExpand={toggleFolderExpanded}
            onRefresh={_handleTreeRefresh}
            onCreateFolder={handleCreateFolder}
            onRenameFolder={handleRenameFolder}
            onDeleteFolder={async (folderId) => {
              await handleDeleteFolder(folderId);
              if (selectedFolderId === folderId) setSelectedFolderId(null);
              await refetch();
            }}
            onMoveFolder={handleMoveFolder}
            onMoveFolders={handleMoveFolders}
            onMoveFile={_handleMoveFilePage}
            onMoveFiles={_handleMoveFiles}
            onRenameFile={_handleRenameFile}
            onDeleteFile={_handleDeleteTreeFile}
            onDeleteFiles={_handleDeleteTreeFiles}
            onDeleteFolders={_handleDeleteTreeFolders}
            onDownloadFolder={handleDownloadFolder}
          />
        </div>

        {/* Resizable divider */}
        <div
          onMouseDown={handleMouseDown}
          style={{
            width: 6,
            cursor: 'col-resize',
            background: isDragging ? 'var(--color-primary, #1976d2)' : 'transparent',
            transition: isDragging ? 'none' : 'background 0.15s',
            flexShrink: 0,
            zIndex: 10,
          }}
          onMouseEnter={(e) => { (e.target as HTMLElement).style.background = 'var(--color-border-hover, #bbb)'; }}
          onMouseLeave={(e) => { if (!isDragging) (e.target as HTMLElement).style.background = 'transparent'; }}
        />

        {/* Right panel: File table */}
        <div style={{ flex: 1, minWidth: 0, overflow: 'auto', display: 'flex', flexDirection: 'column' }}>
          {/* Toolbar above table */}
          <div style={{
            display: 'flex', gap: 8, padding: '8px 12px',
            borderBottom: '1px solid var(--color-border, #e0e0e0)',
            flexShrink: 0, alignItems: 'center', flexWrap: 'wrap',
          }}>
            <button className={styles.secondaryButton} onClick={_handleNewFolder}>
              <FaFolderPlus /> Neuer Ordner
            </button>
            {canCreate && (
              <button className={styles.primaryButton} onClick={handleUploadClick} disabled={uploadingFile}>
                <FaUpload /> {uploadingFile ? 'Uploading...' : 'Datei hochladen'}
              </button>
            )}
          </div>

          {/* Table content */}
          <div style={{ flex: 1, overflow: 'auto' }}>
            {loading && (!files || files.length === 0) ? (
              <div className={styles.loadingContainer}>
                <div className={styles.spinner} />
                <span>Lade Dateien...</span>
              </div>
            ) : filteredFiles.length === 0 ? (
              <div className={styles.emptyState}>
                <FaFolder className={styles.emptyIcon} />
                <h3 className={styles.emptyTitle}>
                  {selectedFolderId ? 'Ordner ist leer' : 'Keine Dateien vorhanden'}
                </h3>
                <p className={styles.emptyDescription}>
                  {selectedFolderId
                    ? 'Verschieben Sie Dateien hierher oder laden Sie neue hoch.'
                    : 'Laden Sie eine Datei hoch, um loszulegen.'}
                </p>
                {canCreate && (
                  <button className={styles.primaryButton} onClick={handleUploadClick} disabled={uploadingFile}>
                    <FaUpload /> Datei hochladen
                  </button>
                )}
              </div>
            ) : (
              <FormGeneratorTable
                data={filteredFiles}
                columns={columns}
                apiEndpoint="/api/files/list"
                loading={loading}
                pagination={true}
                pageSize={25}
                searchable={true}
                filterable={true}
                sortable={true}
                selectable={true}
                onRowSelect={(rows) => setSelectedFiles(rows as UserFile[])}
                rowDraggable={true}
                onRowDragStart={_onRowDragStart}
                getRowDataAttributes={(row: UserFile) =>
                  ({ highlighted: row.id === highlightedFileId ? 'true' : 'false' })
                }
                actionButtons={[
                  ...(canUpdate ? [{
                    type: 'edit' as const,
                    onAction: handleEditClick,
                    title: 'Bearbeiten',
                  }] : []),
                  ...(canDelete ? [{
                    type: 'delete' as const,
                    title: 'Löschen',
                    loading: (row: UserFile) => deletingFiles.has(row.id),
                  }] : []),
                ]}
                customActions={[
                  {
                    id: 'download',
                    icon: <FaDownload />,
                    onClick: handleDownload,
                    title: 'Herunterladen',
                    loading: (row: UserFile) => downloadingFiles.has(row.id),
                  },
                  {
                    id: 'preview',
                    icon: <FaEye />,
                    onClick: handlePreview,
                    title: 'Vorschau',
                    loading: (row: UserFile) => previewingFiles.has(row.id),
                  },
                ]}
                onDelete={handleDelete}
                onDeleteMultiple={handleDeleteMultiple}
                hookData={{
                  refetch: _tableRefetch,
                  permissions,
                  handleDelete: handleFileDelete,
                  handleInlineUpdate,
                  updateOptimistically: updateFileOptimistically,
                }}
                emptyMessage="Keine Dateien gefunden"
              />
            )}
          </div>
        </div>
      </div>

      {/* Edit Modal */}
      {editingFile && (
        <div className={styles.modalOverlay} onClick={() => setEditingFile(null)}>
          <div className={styles.modal} onClick={e => e.stopPropagation()}>
            <div className={styles.modalHeader}>
              <h2 className={styles.modalTitle}>Datei bearbeiten</h2>
              <button className={styles.modalClose} onClick={() => setEditingFile(null)}>✕</button>
            </div>
            <div className={styles.modalContent}>
              {formAttributes.length === 0 ? (
                <div className={styles.loadingContainer}>
                  <div className={styles.spinner} />
                  <span>Lade Formular...</span>
                </div>
              ) : (
                <FormGeneratorForm
                  attributes={formAttributes}
                  data={editingFile}
                  mode="edit"
                  onSubmit={handleEditSubmit}
                  onCancel={() => setEditingFile(null)}
                  submitButtonText="Speichern"
                  cancelButtonText="Abbrechen"
                />
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default FilesPage;
