import React, { useState, useCallback, useRef, useMemo } from 'react';
import { FaFileImport } from 'react-icons/fa';
import type { UdbContext } from './UnifiedDataBar';
import api from '../../api';
import FolderTree from '../../components/FolderTree/FolderTree';
import type { FileNode } from '../../components/FolderTree/FolderTree';
import type { FileAction } from '../../components/FolderTree/actions/types';
import { useFileContext } from '../../contexts/FileContext';
import { useApiRequest } from '../../hooks/useApi';
import {
  importWorkflowFromFile,
  WORKFLOW_FILE_EXTENSION,
} from '../../api/workflowApi';
import { useToast } from '../../contexts/ToastContext';
import styles from './FilesTab.module.css';
import { useLanguage } from '../../providers/language/LanguageContext';

interface FilesTabProps {
  context: UdbContext;
  onFileSelect?: (fileId: string, fileName?: string) => void;
  onSendToChat?: (items: Array<{ id: string; type: 'file' | 'folder'; name: string }>) => void;
  /** Wird aufgerufen, wenn ein ``.workflow.json``-File via Custom-Action in
   * den Graph-Editor importiert wurde. Aktivierung im Editor (Refresh-Liste,
   * Auto-Select) bleibt Aufgabe des Aufrufers. */
  onWorkflowImported?: (workflowId: string) => void;
}

const FilesTab: React.FC<FilesTabProps> = ({ context, onFileSelect, onSendToChat, onWorkflowImported }) => {
  const { t } = useLanguage();
  const { request } = useApiRequest();
  const { showSuccess, showError } = useToast();
  const [searchQuery, setSearchQuery] = useState('');
  const [isDragOver, setIsDragOver] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [selectedFolderId, setSelectedFolderId] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

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

  const _folderNodes = useMemo(() => {
    return folders.map(f => ({
      id: f.id,
      name: f.name,
      parentId: f.parentId ?? null,
      fileCount: f.fileCount ?? 0,
      neutralize: f.neutralize ?? false,
      scope: f.scope ?? 'personal',
    }));
  }, [folders]);

  const _fileNodes: FileNode[] = useMemo(() => {
    let result = treeFileNodes;
    if (searchQuery.trim()) {
      const q = searchQuery.toLowerCase();
      result = result.filter(f =>
        f.fileName.toLowerCase().includes(q),
      );
    }
    return result;
  }, [treeFileNodes, searchQuery]);

  const _refreshAll = useCallback(async () => {
    await Promise.all([refreshTreeFiles(), refreshFolders()]);
  }, [refreshTreeFiles, refreshFolders]);

  const _uploadFiles = useCallback(async (fileList: FileList | File[]) => {
    if (!context.instanceId || uploading) return;
    setUploading(true);
    try {
      for (const file of Array.from(fileList)) {
        const formData = new FormData();
        formData.append('file', file);
        formData.append('featureInstanceId', context.instanceId);
        await api.post('/api/files/upload', formData, {
          headers: { 'Content-Type': 'multipart/form-data' },
        });
      }
      await _refreshAll();
    } catch (err) {
      console.error('File upload failed:', err);
    } finally {
      setUploading(false);
    }
  }, [context.instanceId, uploading, _refreshAll]);

  const _handleDragOver = useCallback((e: React.DragEvent) => {
    if (e.dataTransfer.types.includes('Files')) {
      e.preventDefault();
      e.stopPropagation();
      setIsDragOver(true);
    }
  }, []);

  const _handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);
  }, []);

  const _handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);
    if (e.dataTransfer.files.length > 0) {
      _uploadFiles(e.dataTransfer.files);
    }
  }, [_uploadFiles]);

  const _handleFileInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      _uploadFiles(e.target.files);
      e.target.value = '';
    }
  }, [_uploadFiles]);

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

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

  const _onDeleteFolder = useCallback(async (folderId: string) => {
    await handleDeleteFolder(folderId);
    if (selectedFolderId === folderId) setSelectedFolderId(null);
  }, [handleDeleteFolder, selectedFolderId]);

  const _onRenameFile = useCallback(async (fileId: string, newName: string) => {
    await api.put(`/api/files/${fileId}`, { fileName: newName });
    await refreshTreeFiles();
  }, [refreshTreeFiles]);

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

  const _onDeleteFiles = useCallback(async (fileIds: string[]) => {
    await api.post('/api/files/batch-delete', { fileIds });
    await Promise.all([refreshTreeFiles(), refreshFolders()]);
  }, [refreshTreeFiles, refreshFolders]);

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

  const _onScopeChange = useCallback(async (fileId: string, newScope: string) => {
    updateTreeFileNode(fileId, { scope: newScope });
    try {
      await api.patch(`/api/files/${fileId}/scope`, { scope: newScope });
    } catch (err) {
      console.error('Failed to update scope:', err);
      await refreshTreeFiles();
    }
  }, [updateTreeFileNode, refreshTreeFiles]);

  const _onNeutralizeToggle = useCallback(async (fileId: string, newValue: boolean) => {
    updateTreeFileNode(fileId, { neutralize: newValue });
    try {
      await api.patch(`/api/files/${fileId}/neutralize`, { neutralize: newValue });
    } catch (err) {
      console.error('Failed to toggle neutralize:', err);
      await refreshTreeFiles();
    }
  }, [updateTreeFileNode, refreshTreeFiles]);

  const _onFolderNeutralizeToggle = useCallback(async (folderId: string, newValue: boolean) => {
    try {
      await api.patch(`/api/files/folders/${folderId}/neutralize`, { neutralize: newValue });
      await refreshFolders();
      await refreshTreeFiles();
    } catch (err) {
      console.error('Failed to toggle folder neutralize:', err);
    }
  }, [refreshFolders, refreshTreeFiles]);

  const _customActions: FileAction[] = useMemo(() => {
    if (context.surface !== 'graphEditor') return [];
    return [
      {
        id: 'workflow.openInEditor',
        label: t('In Graph-Editor laden'),
        icon: FaFileImport,
        scope: 'file',
        channels: ['inline', 'menu', 'sheet', 'drop'],
        dragMime: 'application/json+workflow',
        sortOrder: 50,
        predicate: ({ files }) =>
          files.length === 1 &&
          files[0].fileName.toLowerCase().endsWith(WORKFLOW_FILE_EXTENSION),
        handler: async ({ files }) => {
          const file = files[0];
          if (!context.instanceId || !file) return;
          try {
            const result = await importWorkflowFromFile(request, context.instanceId, {
              fileId: file.id,
            });
            const warnings = result?.warnings ?? [];
            const wfId = result?.workflow?.id;
            if (warnings.length > 0) {
              showSuccess(
                t('Workflow importiert ({n} Warnungen). Aktivierung manuell.', {
                  n: String(warnings.length),
                }),
              );
            } else {
              showSuccess(t('Workflow importiert (deaktiviert).'));
            }
            if (wfId && onWorkflowImported) onWorkflowImported(wfId);
          } catch (e: unknown) {
            const msg = e instanceof Error ? e.message : String(e);
            showError(t('Import fehlgeschlagen: {msg}', { msg }));
          }
        },
      },
    ];
  }, [context.surface, context.instanceId, t, request, showSuccess, showError, onWorkflowImported]);

  const _onFolderScopeChange = useCallback(async (folderId: string, newScope: string) => {
    try {
      await api.patch(`/api/files/folders/${folderId}/scope`, { scope: newScope });
      await refreshFolders();
      await refreshTreeFiles();
    } catch (err) {
      console.error('Failed to change folder scope:', err);
    }
  }, [refreshFolders, refreshTreeFiles]);

  if (treeFilesLoading && treeFileNodes.length === 0) {
    return <div className={styles.loading}>{t('Dateien laden')}</div>;
  }

  return (
    <div
      className={styles.filesTab}
      onDragOver={_handleDragOver}
      onDragLeave={_handleDragLeave}
      onDrop={_handleDrop}
    >
      {isDragOver && (
        <div style={{
          position: 'absolute', inset: 0,
          background: 'rgba(25, 118, 210, 0.08)',
          border: '2px dashed #F25843', borderRadius: 8,
          zIndex: 10, display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 13, fontWeight: 600, color: '#F25843',
        }}>
          {t('Dateien hier ablegen')}
        </div>
      )}

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '4px 8px' }}>
        <span style={{ fontSize: 12, fontWeight: 600, color: '#666', textTransform: 'uppercase' }}>{t('Dateien')}</span>
        <div style={{ display: 'flex', gap: 4 }}>
          <button
            onClick={() => fileInputRef.current?.click()}
            disabled={uploading}
            style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 12, color: '#F25843' }}
            title={t('Dateien hochladen')}
          >
            {uploading ? '...' : '+'}
          </button>
          <button
            onClick={_refreshAll}
            style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 12, color: '#F25843' }}
          >
            {'\u21BB'}
          </button>
        </div>
      </div>

      <input
        ref={fileInputRef}
        type="file"
        multiple
        style={{ display: 'none' }}
        onChange={_handleFileInputChange}
      />

      <input
        type="text"
        placeholder={t('Dateien suchen')}
        value={searchQuery}
        onChange={e => setSearchQuery(e.target.value)}
        style={{
          width: '100%', padding: '6px 10px', fontSize: 12, borderRadius: 4,
          border: '1px solid #ddd', boxSizing: 'border-box', margin: '0 0 4px',
        }}
      />

      <div style={{ flex: 1, overflow: 'auto' }}>
        <FolderTree
          folders={_folderNodes}
          files={_fileNodes}
          showFiles={true}
          selectedFolderId={selectedFolderId}
          onSelect={setSelectedFolderId}
          onFileSelect={onFileSelect ? (fileId: string) => {
            const file = treeFileNodes.find(f => f.id === fileId);
            onFileSelect(fileId, file?.fileName);
          } : undefined}
          expandedIds={expandedFolderIds}
          onToggleExpand={toggleFolderExpanded}
          onRefresh={_refreshAll}
          onCreateFolder={handleCreateFolder}
          onRenameFolder={handleRenameFolder}
          onDeleteFolder={_onDeleteFolder}
          onMoveFolder={handleMoveFolder}
          onMoveFolders={handleMoveFolders}
          onMoveFile={_onMoveFile}
          onMoveFiles={_onMoveFiles}
          onRenameFile={_onRenameFile}
          onDeleteFile={_onDeleteFile}
          onDeleteFiles={_onDeleteFiles}
          onDeleteFolders={_onDeleteFolders}
          onDownloadFolder={handleDownloadFolder}
          onScopeChange={_onScopeChange}
          onNeutralizeToggle={_onNeutralizeToggle}
          onFolderScopeChange={_onFolderScopeChange}
          onFolderNeutralizeToggle={_onFolderNeutralizeToggle}
          onSendToChat={onSendToChat}
          customActions={_customActions}
          udbContext={context.surface}
        />

        {_fileNodes.length === 0 && (
          <div style={{ fontSize: 12, color: '#999', textAlign: 'center', padding: 16 }}>
            {searchQuery ? t('Keine Dateien gefunden') : t('Keine Dateien. Drag & Drop zum Hochladen.')}
          </div>
        )}
      </div>

      <div className={styles.legend}>
        <span>{'\uD83D\uDC64'} {t('Persönlich')}</span>
        <span>{'\uD83D\uDC65'} {t('Instanz')}</span>
        <span>{'\uD83C\uDFE2'} {t('Mandant')}</span>
        <span>{'\uD83D\uDD12'} {t('Neutralisiert')}</span>
      </div>
    </div>
  );
};

export default FilesTab;
