/**
 * FilesPage
 *
 * Split-view file management: tree panel on the left (FormGeneratorTree),
 * FormGeneratorTable on the right. Two modes:
 * - "Ordner-Sicht": table filtered by selected folder in the tree
 * - "Alle Dateien": table shows all files without folder filter
 */

import React, { useState, useMemo, useEffect, useRef, useCallback, type PointerEvent as RPointerEvent } from 'react';
import { useUserFiles, useFileOperations, type PaginationParams } from '../../hooks/useFiles';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm } from '../../components/FormGenerator/FormGeneratorForm';
import { FormGeneratorTree } from '../../components/FormGenerator/FormGeneratorTree';
import { createFolderFileProvider } from '../../components/FormGenerator/FormGeneratorTree/providers/FolderFileProvider';
import type { TreeNode } from '../../components/FormGenerator/FormGeneratorTree';
import { FaSync, FaUpload, FaDownload, FaTree, FaTable } from 'react-icons/fa';
import { useToast } from '../../contexts/ToastContext';
import styles from '../admin/Admin.module.css';
import { useLanguage } from '../../providers/language/LanguageContext';
import { getUserDataCache } from '../../utils/userCache';
import { resolveColumnTypes } from '../../utils/columnTypeResolver';

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

type ViewMode = 'folder' | 'all';
type FileOwnerScope = 'all' | 'me' | 'shared';

function normalizeFolderFilterId(folderId: string | null): string | null {
  if (!folderId) return null;
  if (folderId.startsWith('__filesRoot:')) return null;
  return folderId;
}

function isSyntheticRootFolderId(folderId: string | null): boolean {
  return Boolean(folderId && folderId.startsWith('__filesRoot:'));
}

export const FilesPage: React.FC = () => {
  const { t } = useLanguage();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const { showSuccess, showError } = useToast();

  const [viewMode, setViewMode] = useState<ViewMode>('folder');
  const provider = useMemo(() => createFolderFileProvider(), []);
  const [treeKey, setTreeKey] = useState(0);

  // ── Table data ────────────────────────────────────────────────────────
  const {
    data: tableFiles,
    attributes,
    permissions,
    loading: tableLoading,
    error,
    refetch: tableRefetch,
    pagination,
    groupLayout,
    appliedView,
    fetchFileById,
    updateFileOptimistically,
    fetchGroupSectionSummaries: fetchGroupSectionSummariesFromHook,
    refetchForSection: refetchForSectionFromHook,
  } = useUserFiles();

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

  const [editingFile, setEditingFile] = useState<UserFile | null>(null);
  const [selectedFiles, setSelectedFiles] = useState<UserFile[]>([]);
  const [selectedFolderId, setSelectedFolderId] = useState<string | null>(null);
  const [selectedOwnership, setSelectedOwnership] = useState<'own' | 'shared' | null>('own');
  const [highlightedFileId, setHighlightedFileId] = useState<string | null>(null);

  const [treeWidth, setTreeWidth] = useState(300);
  const [treeVisible, setTreeVisible] = useState(true);
  const [tableVisible, setTableVisible] = useState(true);
  const draggingRef = useRef(false);
  const splitContainerRef = useRef<HTMLDivElement>(null);

  const _handleDividerPointerDown = useCallback((e: RPointerEvent<HTMLDivElement>) => {
    e.preventDefault();
    draggingRef.current = true;
    (e.target as HTMLElement).setPointerCapture(e.pointerId);
  }, []);

  const _handleDividerPointerMove = useCallback((e: RPointerEvent<HTMLDivElement>) => {
    if (!draggingRef.current || !splitContainerRef.current) return;
    const rect = splitContainerRef.current.getBoundingClientRect();
    const x = e.clientX - rect.left;
    setTreeWidth(Math.max(180, Math.min(x, rect.width - 200)));
  }, []);

  const _handleDividerPointerUp = useCallback(() => {
    draggingRef.current = false;
  }, []);

  // ── Table refetch wrapper (filters by selectedFolderId in folder mode) ──
  const _tableRefetch = useCallback(async (params?: any) => {
    const nextParams = { ...(params || {}) };
    const nextFilters = { ...(nextParams.filters || {}) };
    const normalizedFolderId = normalizeFolderFilterId(selectedFolderId);
    const rootSelected = isSyntheticRootFolderId(selectedFolderId);
    const owner: FileOwnerScope =
      selectedOwnership === 'own'
        ? 'me'
        : selectedOwnership === 'shared'
          ? 'shared'
          : 'all';
    if (viewMode === 'folder' && selectedFolderId && !rootSelected) {
      nextFilters.folderId = normalizedFolderId;
    } else {
      delete nextFilters.folderId;
    }
    nextParams.filters = nextFilters;
    if (owner !== 'all') nextParams.owner = owner;
    else delete nextParams.owner;
    await tableRefetch(nextParams);
  }, [tableRefetch, selectedFolderId, selectedOwnership, viewMode]);

  const fetchGroupSectionSummaries = useCallback(
    async (base: {
      search?: string;
      filters?: Record<string, unknown>;
      sort?: Array<{ field: string; direction: string }>;
      viewKey?: string | null;
      groupField: string;
      groupDirection?: 'asc' | 'desc';
    }) => {
      const filters = { ...(base.filters || {}) };
      const normalizedFolderId = normalizeFolderFilterId(selectedFolderId);
      const rootSelected = isSyntheticRootFolderId(selectedFolderId);
      if (viewMode === 'folder' && selectedFolderId && !rootSelected) {
        filters.folderId = normalizedFolderId;
      }
      const owner: FileOwnerScope =
        selectedOwnership === 'own'
          ? 'me'
          : selectedOwnership === 'shared'
            ? 'shared'
            : 'all';
      return fetchGroupSectionSummariesFromHook({ ...base, filters, owner });
    },
    [fetchGroupSectionSummariesFromHook, viewMode, selectedFolderId, selectedOwnership],
  );

  const refetchForSection = useCallback(
    async (
      paginationParams: PaginationParams & { page: number; pageSize: number },
      sectionFilter: Record<string, unknown>,
      parentColumnFilters?: Record<string, unknown>,
    ) => {
      const merged = { ...(parentColumnFilters || {}) };
      const normalizedFolderId = normalizeFolderFilterId(selectedFolderId);
      const rootSelected = isSyntheticRootFolderId(selectedFolderId);
      if (viewMode === 'folder' && selectedFolderId && !rootSelected) {
        merged.folderId = normalizedFolderId;
      }
      const owner: FileOwnerScope =
        selectedOwnership === 'own'
          ? 'me'
          : selectedOwnership === 'shared'
            ? 'shared'
            : 'all';
      return refetchForSectionFromHook({ ...paginationParams, owner }, sectionFilter, merged);
    },
    [refetchForSectionFromHook, viewMode, selectedFolderId, selectedOwnership],
  );

  const _refreshAll = useCallback(async () => {
    await _tableRefetch({ page: 1, pageSize: 25 });
    setTreeKey(k => k + 1);
  }, [_tableRefetch]);

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

  // ── Tree interaction ──────────────────────────────────────────────────
  const _handleTreeNodeClick = useCallback((node: TreeNode) => {
    setSelectedOwnership(node.ownership);
    if (node.type === 'folder') {
      setSelectedFolderId(node.id);
    } else if (node.type === 'file') {
      setSelectedFolderId(node.parentId ?? null);
      setHighlightedFileId(node.id);
      requestAnimationFrame(() => {
        const row = document.querySelector('tr[data-highlighted="true"]');
        if (row) row.scrollIntoView({ behavior: 'smooth', block: 'center' });
      });
      setTimeout(() => setHighlightedFileId(null), 2500);
    }
  }, []);

  // ── Columns ───────────────────────────────────────────────────────────
  const columns = useMemo(() => {
    const hiddenColumns = ['id', 'fileHash', 'folderId'];
    const cols = (attributes || [])
      .filter(attr => !hiddenColumns.includes(attr.name))
      .map(attr => ({
        key: attr.name,
        label: attr.label || attr.name,
        sortable: attr.sortable !== false,
        filterable: attr.filterable !== false,
        searchable: attr.searchable !== false,
        width: attr.width || 150,
        minWidth: attr.minWidth || 100,
        maxWidth: attr.maxWidth || 400,
        displayField: (attr as any).displayField,
        frontendFormat: (attr as any).frontendFormat,
        frontendFormatLabels: (attr as any).frontendFormatLabels,
      }));
    cols.push({
      key: 'sysCreatedBy',
      label: t('Erstellt von'),
      sortable: true,
      filterable: true,
      searchable: true,
      width: 150,
      minWidth: 100,
      maxWidth: 250,
      displayField: 'sysCreatedByLabel',
    } as any);
    cols.push({
      key: 'sysModifiedAt',
      label: t('Geaendert am'),
      type: 'timestamp',
      sortable: true,
      filterable: true,
      searchable: false,
      width: 170,
      minWidth: 130,
      maxWidth: 220,
    } as any);
    return resolveColumnTypes(cols, attributes || []);
  }, [attributes, t]);

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

  const currentUserId = useMemo(() => getUserDataCache()?.id || '', []);
  const _isOwned = useCallback((row: UserFile) => row.sysCreatedBy === currentUserId, [currentUserId]);

  // ── Table event handlers ──────────────────────────────────────────────
  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 changes: Record<string, any> = {};
    const editableFields = ['fileName', 'scope', 'tags', 'description', 'neutralize'] as const;
    for (const field of editableFields) {
      if (data[field] !== undefined && data[field] !== editingFile[field]) {
        changes[field] = data[field];
      }
    }
    if (Object.keys(changes).length === 0 && data.fileName) {
      changes.fileName = data.fileName;
    }
    const result = await handleFileUpdate(editingFile.id, changes);
    if (result.success) {
      setEditingFile(null);
      await _tableRefetch();
    }
  };

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

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

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

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

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

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

  const formAttributes = useMemo(() => {
    const excludedFields = ['id', 'mandateId', 'fileHash', 'folderId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', '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}>&#9888;&#65039;</span>
          <p className={styles.errorMessage}>{t('Fehler beim Laden der Dateien: {detail}', { detail: String(error) })}</p>
          <button className={styles.secondaryButton} onClick={() => _tableRefetch()}>
            <FaSync /> {t('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}>{t('Dateien')}</h1>
          <p className={styles.pageSubtitle}>{t('Dateiverwaltung')}</p>
        </div>
        <div className={styles.headerActions}>
          <div style={{ display: 'flex', gap: 4, marginRight: 8 }}>
            <button
              className={treeVisible ? styles.primaryButton : styles.secondaryButton}
              onClick={() => { if (!treeVisible || tableVisible) setTreeVisible(v => !v); }}
              style={{ fontSize: 12, padding: '4px 8px' }}
              title={treeVisible ? t('Ordnerstruktur ausblenden') : t('Ordnerstruktur einblenden')}
            >
              <FaTree />
            </button>
            <button
              className={tableVisible ? styles.primaryButton : styles.secondaryButton}
              onClick={() => { if (!tableVisible || treeVisible) setTableVisible(v => !v); }}
              style={{ fontSize: 12, padding: '4px 8px' }}
              title={tableVisible ? t('Tabelle ausblenden') : t('Tabelle einblenden')}
            >
              <FaTable />
            </button>
          </div>
          <button className={styles.secondaryButton} onClick={_refreshAll} disabled={tableLoading}>
            <FaSync className={tableLoading ? 'spinning' : ''} /> {t('Aktualisieren')}
          </button>
        </div>
      </div>

      <div ref={splitContainerRef} style={{ flex: 1, overflow: 'hidden', display: 'flex', minHeight: 0 }}>
        {/* Left panel: Tree */}
        {treeVisible && (
          <div style={{
            width: tableVisible ? treeWidth : '100%',
            flexShrink: 0,
            overflow: 'auto',
            display: 'flex', flexDirection: 'column',
          }}>
            <FormGeneratorTree
              key={`own-${treeKey}`}
              provider={provider}
              ownership="own"
              title={t('Eigene')}
              showFilter={true}
              allowCreateFolder={canCreate}
              onNodeClick={_handleTreeNodeClick}
              onRefresh={() => _tableRefetch()}
            />
            <FormGeneratorTree
              key={`shared-${treeKey}`}
              provider={provider}
              ownership="shared"
              title={t('Geteilt mit mir')}
              collapsible={true}
              defaultCollapsed={true}
              emptyMessage={t('Keine geteilten Dateien')}
              onNodeClick={_handleTreeNodeClick}
            />
          </div>
        )}

        {/* Resizable divider */}
        {treeVisible && tableVisible && (
          <div
            onPointerDown={_handleDividerPointerDown}
            onPointerMove={_handleDividerPointerMove}
            onPointerUp={_handleDividerPointerUp}
            style={{
              width: 6, cursor: 'col-resize', flexShrink: 0,
              background: 'var(--color-border, #e0e0e0)',
              position: 'relative', zIndex: 2,
              touchAction: 'none',
            }}
          >
            <div style={{
              position: 'absolute', top: '50%', left: '50%',
              transform: 'translate(-50%, -50%)',
              width: 4, height: 32, borderRadius: 2,
              background: 'var(--color-text-muted, #94a3b8)',
              opacity: 0.4,
            }} />
          </div>
        )}

        {/* Right panel: Table with view-mode toggle */}
        {tableVisible && (
        <div style={{ flex: 1, overflow: 'auto', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
          <div style={{
            display: 'flex', gap: 8, padding: '8px 12px',
            borderBottom: '1px solid var(--color-border, #e0e0e0)',
            flexShrink: 0, alignItems: 'center', flexWrap: 'wrap',
          }}>
            <button
              className={viewMode === 'folder' ? styles.primaryButton : styles.secondaryButton}
              onClick={() => setViewMode('folder')}
              style={{ fontSize: 12, padding: '4px 10px' }}
            >
              {t('Ordner-Sicht')}
            </button>
            <button
              className={viewMode === 'all' ? styles.primaryButton : styles.secondaryButton}
              onClick={() => setViewMode('all')}
              style={{ fontSize: 12, padding: '4px 10px' }}
            >
              {t('Alle Dateien')}
            </button>

            <div style={{ flex: 1 }} />

            {canCreate && (
              <button className={styles.primaryButton} onClick={handleUploadClick} disabled={uploadingFile}>
                <FaUpload /> {uploadingFile ? t('Wird hochgeladen...') : t('Datei hochladen')}
              </button>
            )}
          </div>

          <div style={{ flex: 1, overflow: 'auto' }}>
            <FormGeneratorTable
              data={tableFiles || []}
              columns={columns}
              apiEndpoint="/api/files/list"
              tableContextKey="files/list"
              tableGroupLayoutMode="inline"
              loading={tableLoading}
              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={[
                {
                  type: 'view' as const,
                  onAction: () => {},
                  title: t('Vorschau'),
                  idField: 'id',
                  nameField: 'fileName',
                  typeField: 'mimeType',
                  loadingStateName: 'previewingFiles',
                },
                ...(canUpdate ? [{
                  type: 'edit' as const,
                  onAction: handleEditClick,
                  title: t('Bearbeiten'),
                  disabled: (row: UserFile) => !_isOwned(row) ? { disabled: true, message: t('Nur Eigentuemer kann bearbeiten') } : false,
                }] : []),
                ...(canDelete ? [{
                  type: 'delete' as const,
                  title: t('Loeschen'),
                  loading: (row: UserFile) => deletingFiles.has(row.id),
                  disabled: (row: UserFile) => !_isOwned(row) ? { disabled: true, message: t('Nur Eigentuemer kann loeschen') } : false,
                }] : []),
              ]}
              customActions={[
                {
                  id: 'download',
                  icon: <FaDownload />,
                  onClick: handleDownload,
                  title: t('Herunterladen'),
                  loading: (row: UserFile) => downloadingFiles.has(row.id),
                },
              ]}
              onDelete={handleDelete}
              onDeleteMultiple={handleDeleteMultiple}
              hookData={{
                refetch: _tableRefetch,
                pagination,
                groupLayout,
                appliedView,
                permissions,
                handleDelete: handleFileDelete,
                handleInlineUpdate,
                updateOptimistically: updateFileOptimistically,
                previewingFiles,
                fetchGroupSectionSummaries,
                refetchForSection,
              }}
              emptyMessage={t('Keine Dateien gefunden')}
            />
          </div>
        </div>
        )}
      </div>

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

export default FilesPage;
