import React, { useCallback, useRef, useMemo, useState, useEffect } from 'react';
import type { UdbContext } from './UnifiedDataBar';
import api from '../../api';
import { useApiRequest } from '../../hooks/useApi';
import {
  importWorkflowFromFile,
  WORKFLOW_FILE_EXTENSION,
} from '../../api/workflowApi';
import { useToast } from '../../contexts/ToastContext';
import { FormGeneratorTree } from '../FormGenerator/FormGeneratorTree';
import { createFolderFileProvider } from '../FormGenerator/FormGeneratorTree/providers/FolderFileProvider';
import type { TreeNode } from '../FormGenerator/FormGeneratorTree';
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' | 'group'; name: string }>) => void;
  /** Wird aufgerufen, wenn ein ``.workflow.json``-File via Custom-Action in
   * den Graph-Editor importiert wurde. */
  onWorkflowImported?: (workflowId: string) => void;
}

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

  const provider = useMemo(() => createFolderFileProvider(), []);
  const [ownTreeKey, setOwnTreeKey] = useState(0);
  const [sharedTreeKey, setSharedTreeKey] = useState(0);

  const _handleNodeClick = useCallback((node: TreeNode) => {
    if (node.type === 'file') {
      onFileSelect?.(node.id, node.name);
    }
  }, [onFileSelect]);

  const _handleRefresh = useCallback(() => {
    setOwnTreeKey(k => k + 1);
    setSharedTreeKey(k => k + 1);
  }, []);

  useEffect(() => {
    const _onFileUploaded = () => _handleRefresh();
    window.addEventListener('fileUploaded', _onFileUploaded);
    return () => window.removeEventListener('fileUploaded', _onFileUploaded);
  }, [_handleRefresh]);

  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' },
        });
      }
      _handleRefresh();
    } catch (err) {
      console.error('File upload failed:', err);
    } finally {
      setUploading(false);
    }
  }, [context.instanceId, uploading, _handleRefresh]);

  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();
    if (!e.relatedTarget || !(e.currentTarget as Node).contains(e.relatedTarget as Node)) {
      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]);

  /* Workflow import is only available when embedded in the graph editor */
  const _handleWorkflowImport = useCallback(async (fileId: string, fileName: string) => {
    if (context.surface !== 'graphEditor' || !context.instanceId) return;
    if (!fileName?.toLowerCase().endsWith(WORKFLOW_FILE_EXTENSION)) return;
    try {
      const result = await importWorkflowFromFile(request, context.instanceId, { fileId });
      const warnings = result?.warnings ?? [];
      const wfId = result?.workflow?.id;
      if (warnings.length > 0) {
        showSuccess(t('Workflow importiert ({n} Warnungen).', { 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, request, showSuccess, showError, t, onWorkflowImported]);

  const _handleNodeClickWithImport = useCallback((node: TreeNode) => {
    _handleNodeClick(node);
    if (node.type === 'file') {
      _handleWorkflowImport(node.id, node.name);
    }
  }, [_handleNodeClick, _handleWorkflowImport]);

  const _handleSendToChat = useCallback((node: TreeNode) => {
    onSendToChat?.([{ id: node.id, type: node.type === 'folder' ? 'group' : 'file', name: node.name }]);
  }, [onSendToChat]);

  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',
            pointerEvents: 'auto',
          }}
          onDragOver={(e) => { e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = 'copy'; }}
          onDragLeave={(e) => {
            if (!e.relatedTarget || !(e.currentTarget as Node).contains(e.relatedTarget as Node)) {
              setIsDragOver(false);
            }
          }}
          onDrop={_handleDrop}
        >
          {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={_handleRefresh}
            style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 12, color: '#F25843' }}
            title={t('Aktualisieren')}
          >
            {'\u21BB'}
          </button>
        </div>
      </div>

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

      <div style={{ flex: 1, overflow: 'auto', minHeight: 0 }}>
        <FormGeneratorTree
          key={`own-${ownTreeKey}`}
          provider={provider}
          ownership="own"
          title={t('Eigene')}
          compact={true}
          showFilter={true}
          onNodeClick={_handleNodeClickWithImport}
          onSendToChat={_handleSendToChat}
        />
        <FormGeneratorTree
          key={`shared-${sharedTreeKey}`}
          provider={provider}
          ownership="shared"
          title={t('Geteilt mit mir')}
          compact={true}
          collapsible={true}
          defaultCollapsed={true}
          emptyMessage={t('Keine geteilten Dateien')}
          onNodeClick={_handleNodeClickWithImport}
          onSendToChat={_handleSendToChat}
        />
      </div>

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

export default FilesTab;
