import React, { createContext, useContext, useCallback, useState, useEffect } from 'react';
import api from '../api';
import { useUserFiles, useFileOperations, UserFile } from '../hooks/useFiles';
import type { FolderInfo } from '../api/fileApi';

export type { FolderInfo };

interface FileContextType {
  files: UserFile[];
  loading: boolean;
  error: string | null;
  refetch: () => Promise<void>;
  handleFileUpload: (file: File, workflowId?: string) => Promise<{ success: boolean; fileData?: any; error?: string }>;
  handleFileDelete: (fileId: string, onOptimisticDelete?: () => void) => Promise<boolean>;
  handleFilePreview: (fileId: string, fileName: string, mimeType?: string) => Promise<{ success: boolean; previewUrl?: string | null; blob?: Blob | null; isJsonContent?: boolean; decodedContent?: any; isTextContent?: boolean; error?: string }>;
  handleFileDownload: (fileId: string, fileName: string) => Promise<void>;
  uploadingFile: boolean;
  deletingFiles: Set<string>;
  previewingFiles: Set<string>;
  downloadingFiles: Set<string>;
  folders: FolderInfo[];
  foldersLoading: boolean;
  refreshFolders: () => Promise<void>;
  handleCreateFolder: (name: string, parentId: string | null) => Promise<void>;
  handleRenameFolder: (folderId: string, newName: string) => Promise<void>;
  handleDeleteFolder: (folderId: string) => Promise<void>;
  handleMoveFolder: (folderId: string, targetParentId: string | null) => Promise<void>;
  handleMoveFile: (fileId: string, targetFolderId: string | null) => Promise<void>;
  handleMoveFiles: (fileIds: string[], targetFolderId: string | null) => Promise<void>;
  handleMoveFolders: (folderIds: string[], targetParentId: string | null) => Promise<void>;
  handleDownloadFolder: (folderId: string, folderName: string) => Promise<void>;
  expandedFolderIds: Set<string>;
  toggleFolderExpanded: (id: string) => void;
}

export const FileContext = createContext<FileContextType | undefined>(undefined);

export function FileProvider({ children }: { children: React.ReactNode }) {
  const { data: files, loading, error, refetch: refetchFiles, removeFileOptimistically } = useUserFiles();
  const {
    handleFileUpload: hookHandleFileUpload,
    handleFileDelete: hookHandleFileDelete,
    handleFilePreview,
    handleFileDownload,
    uploadingFile,
    deletingFiles,
    previewingFiles,
    downloadingFiles
  } = useFileOperations();

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

  // ── Folder expanded state (persisted in localStorage) ───────────────────
  const _STORAGE_KEY = 'folderTree-expandedIds';
  const [expandedFolderIds, setExpandedFolderIds] = useState<Set<string>>(() => {
    try {
      const stored = localStorage.getItem(_STORAGE_KEY);
      return stored ? new Set<string>(JSON.parse(stored)) : new Set<string>();
    } catch { return new Set<string>(); }
  });

  const toggleFolderExpanded = useCallback((id: string) => {
    setExpandedFolderIds(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      try { localStorage.setItem(_STORAGE_KEY, JSON.stringify([...next])); } catch {}
      return next;
    });
  }, []);

  // ── Folder state (single source of truth) ──────────────────────────────
  const [folders, setFolders] = useState<FolderInfo[]>([]);
  const [foldersLoading, setFoldersLoading] = useState(false);

  const refreshFolders = useCallback(async () => {
    setFoldersLoading(true);
    try {
      const response = await api.get('/api/files/folders');
      const data = Array.isArray(response.data) ? response.data : [];
      setFolders(data);
    } catch (err) {
      console.error('Failed to load folders:', err);
    } finally {
      setFoldersLoading(false);
    }
  }, []);

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

  const handleCreateFolder = useCallback(async (name: string, parentId: string | null) => {
    await api.post('/api/files/folders', { name, parentId: parentId || null });
    await refreshFolders();
  }, [refreshFolders]);

  const handleRenameFolder = useCallback(async (folderId: string, newName: string) => {
    await api.put(`/api/files/folders/${folderId}`, { name: newName });
    await refreshFolders();
  }, [refreshFolders]);

  const handleDeleteFolder = useCallback(async (folderId: string) => {
    await api.delete(`/api/files/folders/${folderId}`, { params: { recursive: true } });
    await refreshFolders();
    await refetchFiles();
  }, [refreshFolders, refetchFiles]);

  const handleMoveFolder = useCallback(async (folderId: string, targetParentId: string | null) => {
    await api.post(`/api/files/folders/${folderId}/move`, { targetParentId });
    await refreshFolders();
  }, [refreshFolders]);

  const handleMoveFile = useCallback(async (fileId: string, targetFolderId: string | null) => {
    await api.post(`/api/files/${fileId}/move`, { targetFolderId });
    await refetchFiles();
  }, [refetchFiles]);

  const handleMoveFiles = useCallback(async (fileIds: string[], targetFolderId: string | null) => {
    await api.post('/api/files/batch-move', { fileIds, targetFolderId });
    await refetchFiles();
  }, [refetchFiles]);

  const handleMoveFolders = useCallback(async (folderIds: string[], targetParentId: string | null) => {
    await api.post('/api/files/batch-move', { folderIds, targetParentId });
    await refreshFolders();
  }, [refreshFolders]);

  const handleDownloadFolder = useCallback(async (folderId: string, folderName: string) => {
    try {
      const response = await api.get(`/api/files/folders/${folderId}/download`, {
        responseType: 'blob',
      });
      const url = window.URL.createObjectURL(response.data);
      const link = document.createElement('a');
      link.href = url;
      link.setAttribute('download', `${folderName}.zip`);
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(url);
    } catch (err) {
      console.error('Failed to download folder:', err);
    }
  }, []);

  // ── File operations ────────────────────────────────────────────────────

  const handleFileUpload = useCallback(async (file: File, workflowId?: string) => {
    const result = await hookHandleFileUpload(file, workflowId);
    if (result.success && result.fileData) {
      await refetchFiles();
    }
    return result;
  }, [hookHandleFileUpload, refetchFiles]);

  const handleFileDelete = useCallback(async (fileId: string, onOptimisticDelete?: () => void) => {
    const success = await hookHandleFileDelete(fileId, () => {
      removeFileOptimistically(fileId);
      onOptimisticDelete?.();
    });
    if (success) {
      await refetchFiles();
    }
    return success;
  }, [hookHandleFileDelete, removeFileOptimistically, refetchFiles]);

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

  return (
    <FileContext.Provider
      value={{
        files,
        loading,
        error,
        refetch,
        handleFileUpload,
        handleFileDelete,
        handleFilePreview: handleFilePreview as FileContextType['handleFilePreview'],
        handleFileDownload: async (fileId: string, fileName: string) => {
          await handleFileDownload(fileId, fileName);
        },
        uploadingFile,
        deletingFiles,
        previewingFiles,
        downloadingFiles,
        folders,
        foldersLoading,
        refreshFolders,
        handleCreateFolder,
        handleRenameFolder,
        handleDeleteFolder,
        handleMoveFolder,
        handleMoveFile,
        handleMoveFiles,
        handleMoveFolders,
        handleDownloadFolder,
        expandedFolderIds,
        toggleFolderExpanded,
      }}
    >
      {children}
    </FileContext.Provider>
  );
}

export function useFileContext() {
  const context = useContext(FileContext);
  if (context === undefined) {
    throw new Error('useFileContext must be used within a FileProvider');
  }
  return context;
}
