import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useApiRequest } from '../useApi';
import { useWorkflowSelection } from '../../contexts/WorkflowSelectionContext';
import { useFileContext } from '../../contexts/FileContext';
import { MessageDocument } from '../../components/UiComponents/Messages/MessagesTypes';
import { usePrompts } from '../usePrompts';
import { usePermissions } from '../usePermissions';
import { deleteFileFromMessageApi } from '../../api/workflowApi';
import type { Workflow, WorkflowMessage } from '../../api/workflowApi';
import { useWorkflowLifecycle } from './useWorkflowLifecycle';
import { useWorkflows } from './useWorkflows';
import { useDashboardLogTree } from './useDashboardLogTree';
import { extractFileIdsFromMessage, convertFilesToDocuments, sortMessages } from './playgroundUtils';
import type { WorkflowLog as LogTypesWorkflowLog } from '../../components/UiComponents/Log/LogTypes';

export interface WorkflowFile {
  id: string;
  fileId: string;
  fileName: string;
  fileSize: number;
  mimeType: string;
  messageId?: string;
  source?: 'user_uploaded' | 'ai_created';
}

export function useDashboardInputForm() {
  const [inputValue, setInputValue] = useState<string>('');
  const [pendingFiles, setPendingFiles] = useState<WorkflowFile[]>([]);
  const [isFileAttachmentPopupOpen, setIsFileAttachmentPopupOpen] = useState(false);
  const [optimisticMessage, setOptimisticMessage] = useState<WorkflowMessage | null>(null);
  const [selectedPromptId, setSelectedPromptId] = useState<string | null>(null);
  const [workflowMode, setWorkflowMode] = useState<'Dynamic' | 'Automation' | null>(null);
  
  const { checkPermission, canView } = usePermissions();
  const [playgroundUIPermission, setPlaygroundUIPermission] = useState<boolean>(false);
  const [chatWorkflowPermission, setChatWorkflowPermission] = useState<any>(null);
  const [promptPermission, setPromptPermission] = useState<any>(null);
  const [filePermission, setFilePermission] = useState<any>(null);
  
  const { selectedWorkflowId, selectWorkflow: selectWorkflowFromContext, clearWorkflow: clearWorkflowFromContext } = useWorkflowSelection();
  const {
    workflowId,
    workflowStatus,
    currentRound,
    isRunning,
    isStopping,
    startingWorkflow,
    messages,
    dashboardLogs,
    unifiedContentLogs,
    latestStats,
    startWorkflow,
    stopWorkflow,
    resetWorkflow,
    selectWorkflow,
    setWorkflowStatusOptimistic
  } = useWorkflowLifecycle();

  // Dashboard log tree hook
  const {
    tree: dashboardTree,
    processDashboardLogs,
    clearDashboard,
    toggleOperationExpanded,
    toggleRoundExpanded,
    updateCurrentRound,
    getChildOperations
  } = useDashboardLogTree();
  
  // Ref to prevent infinite sync loops
  const isSyncingRef = useRef(false);
  
  const fileContext = useFileContext();
  const { request } = useApiRequest();
  const { prompts, loading: promptsLoading, permissions: promptsPermissions, fetchPromptById } = usePrompts();
  
  useEffect(() => {
    if (promptsPermissions) {
      setPromptPermission(promptsPermissions);
    }
  }, [promptsPermissions]);
  
  useEffect(() => {
    const checkPermissions = async () => {
      try {
        const uiPerm = await canView('UI', 'ui.system.playground');
        setPlaygroundUIPermission(uiPerm);
        
        if (uiPerm) {
          const chatWorkflowPerm = await checkPermission('DATA', 'ChatWorkflow');
          setChatWorkflowPermission(chatWorkflowPerm);
          const promptPerm = await checkPermission('DATA', 'Prompt');
          setPromptPermission(promptPerm);
          const filePerm = await checkPermission('DATA', 'FileItem');
          setFilePermission(filePerm);
        }
      } catch (error) {
      }
    };
    
    checkPermissions();
  }, [canView, checkPermission]);
  
  // Sync context -> lifecycle: When context selection changes, update lifecycle
  useEffect(() => {
    if (isSyncingRef.current) return;
    
    if (selectedWorkflowId && selectedWorkflowId !== workflowId) {
      isSyncingRef.current = true;
      selectWorkflow(selectedWorkflowId).finally(() => {
        isSyncingRef.current = false;
      });
    } else if (!selectedWorkflowId && workflowId) {
      // If context is cleared but lifecycle still has a workflow, reset lifecycle
      isSyncingRef.current = true;
      resetWorkflow();
      isSyncingRef.current = false;
    }
  }, [selectedWorkflowId, workflowId, selectWorkflow, resetWorkflow]);

  // Sync lifecycle -> context: When lifecycle workflowId changes, update context
  useEffect(() => {
    if (isSyncingRef.current) return;
    
    if (workflowId && workflowId !== selectedWorkflowId) {
      isSyncingRef.current = true;
      selectWorkflowFromContext(workflowId);
      isSyncingRef.current = false;
    } else if (!workflowId && selectedWorkflowId) {
      // If lifecycle is cleared but context still has selection, clear context
      isSyncingRef.current = true;
      clearWorkflowFromContext();
      isSyncingRef.current = false;
    }
  }, [workflowId, selectedWorkflowId, selectWorkflowFromContext, clearWorkflowFromContext]);

  useEffect(() => {
    const handleSetInput = (event: CustomEvent<{ value: string }>) => {
      const newValue = event.detail.value;
      if (newValue && typeof newValue === 'string') {
        setInputValue(newValue);
      }
    };

    window.addEventListener('dashboardSetInput', handleSetInput as EventListener);
    return () => {
      window.removeEventListener('dashboardSetInput', handleSetInput as EventListener);
    };
  }, []);
  
  const { workflows, loading: workflowsLoading, refetch: refetchWorkflows } = useWorkflows();

  // Track processed log IDs to avoid reprocessing
  const processedLogIdsRef = useRef<Set<string>>(new Set());
  const lastWorkflowIdRef = useRef<string | null>(null);
  const lastDashboardLogsLengthRef = useRef<number>(0);

  // Clear processed logs when workflow changes
  useEffect(() => {
    if (workflowId !== lastWorkflowIdRef.current) {
      processedLogIdsRef.current.clear();
      lastWorkflowIdRef.current = workflowId || null;
      lastDashboardLogsLengthRef.current = 0;
      if (!workflowId) {
        clearDashboard(true);
      }
    }
  }, [workflowId, clearDashboard]);

  // Process dashboard logs when they change (only new logs)
  useEffect(() => {
    if (!dashboardLogs || dashboardLogs.length === 0) {
      lastDashboardLogsLengthRef.current = 0;
      return;
    }

    // Only process if the array length changed (indicating new logs)
    if (dashboardLogs.length === lastDashboardLogsLengthRef.current) {
      return;
    }

    // Filter to only new logs that haven't been processed
    const newLogs = dashboardLogs.filter(log => {
      const logId = log.id || `${log.operationId}-${log.timestamp}`;
      if (processedLogIdsRef.current.has(logId)) {
        return false;
      }
      processedLogIdsRef.current.add(logId);
      return true;
    });

    // Only process if there are new logs
    if (newLogs.length > 0) {
      // Convert API WorkflowLog format to LogTypes WorkflowLog format
      const convertedLogs: LogTypesWorkflowLog[] = newLogs.map(log => ({
        id: log.id || `${log.operationId || 'unknown'}-${log.timestamp || Date.now()}`,
        workflowId: log.workflowId || '',
        message: log.message || '',
        type: log.type,
        timestamp: log.timestamp || Date.now(),
        status: log.status,
        progress: log.progress,
        performance: log.performance,
        parentId: log.parentId,
        operationId: log.operationId
      }));
      processDashboardLogs(convertedLogs);
    }

    lastDashboardLogsLengthRef.current = dashboardLogs.length;
  }, [dashboardLogs, processDashboardLogs]);

  // Update current round in dashboard tree when it changes
  useEffect(() => {
    if (currentRound !== undefined) {
      updateCurrentRound(currentRound);
    }
  }, [currentRound, updateCurrentRound]);
  
  const workflowFiles = useMemo(() => {
    const fileMap = new Map<string, WorkflowFile>();
    const pendingFileIds = new Set(pendingFiles.map(f => f.fileId));
    
    const addFilesFromMessage = (message: WorkflowMessage, messageId: string) => {
      const documents = (message as any).documents as MessageDocument[] | undefined;
      const files = (message as any).files as any[] | undefined;
      
      if (documents && Array.isArray(documents)) {
        documents.forEach((doc: MessageDocument) => {
          if (!doc.fileId || doc.fileId.trim() === '') return;
          if (!fileMap.has(doc.fileId)) {
            const source = pendingFileIds.has(doc.fileId) ? 'user_uploaded' : 'ai_created';
            fileMap.set(doc.fileId, {
              id: doc.id || doc.fileId,
              fileId: doc.fileId,
              fileName: doc.fileName || 'Unknown File',
              fileSize: doc.fileSize || 0,
              mimeType: doc.mimeType || 'application/octet-stream',
              messageId: doc.messageId || messageId,
              source
            });
          }
        });
      }
      
      if (files && Array.isArray(files)) {
        files.forEach((file: any) => {
          const fileId = file.id || file.fileId;
          if (!fileId || fileId.trim() === '') return;
          if (!fileMap.has(fileId)) {
            const source = pendingFileIds.has(fileId) ? 'user_uploaded' : 'ai_created';
            fileMap.set(fileId, {
              id: fileId,
              fileId: fileId,
              fileName: file.fileName || file.name || 'Unknown File',
              fileSize: file.fileSize || file.size || 0,
              mimeType: file.mimeType || file.mime_type || 'application/octet-stream',
              messageId: messageId,
              source
            });
          }
        });
      }
    };
    
    if (messages && messages.length > 0) {
      messages.forEach((message: WorkflowMessage) => {
        addFilesFromMessage(message, message.id);
      });
    }
    
    if (optimisticMessage) {
      addFilesFromMessage(optimisticMessage, optimisticMessage.id || 'optimistic');
    }
    
    return Array.from(fileMap.values());
  }, [messages, pendingFiles, optimisticMessage]);

  useEffect(() => {
    if (!messages || messages.length === 0) return;

    const messageTexts = new Set<string>();
    messages.forEach((message: WorkflowMessage) => {
      if (message.message) {
        messageTexts.add(message.message.trim());
      }
    });

    if (optimisticMessage && optimisticMessage.message) {
      const optimisticText = optimisticMessage.message.trim();
      const optimisticFileIds = extractFileIdsFromMessage(optimisticMessage);
      
      const matchingMessage = Array.from(messages).find((msg: WorkflowMessage) => 
        msg.message && msg.message.trim() === optimisticText
      );
      
      if (matchingMessage) {
        const matchingFileIds = extractFileIdsFromMessage(matchingMessage);
        
        if (optimisticFileIds.size > 0) {
          const allFilesConfirmed = Array.from(optimisticFileIds).every(fileId => 
            matchingFileIds.has(fileId)
          );
          if (allFilesConfirmed && matchingFileIds.size > 0) {
            setOptimisticMessage(null);
          }
        } else {
          if (messageTexts.has(optimisticText)) {
            setOptimisticMessage(null);
          }
        }
      }
    }
  }, [messages, optimisticMessage]);

  const displayMessages = useMemo(() => {
    const optimisticText = optimisticMessage?.message?.trim();
    
    const processedMessages = (messages || []).map((message: WorkflowMessage) => {
      const files = (message as any).files as any[] | undefined;
      const documents = (message as any).documents as MessageDocument[] | undefined;
      
      if (files && Array.isArray(files) && (!documents || documents.length === 0)) {
        return {
          ...message,
          documents: convertFilesToDocuments(files, message.id)
        };
      }
      
      return message;
    });
    
    let replacedMessageTimestamp: number | undefined;
    const filteredMessages = processedMessages.filter((message: WorkflowMessage) => {
      const isUserMessage = message.role?.toLowerCase() === 'user';
      const messageText = message.message?.trim();
      
      if (optimisticMessage && optimisticText && isUserMessage && messageText === optimisticText) {
        const documents = (message as any).documents as MessageDocument[] | undefined;
        const files = (message as any).files as any[] | undefined;
        const hasDocuments = documents && Array.isArray(documents) && documents.length > 0;
        const hasFiles = files && Array.isArray(files) && files.length > 0;
        
        if (hasDocuments || hasFiles) {
          return true;
        }
        
        if (message.publishedAt !== undefined) {
          replacedMessageTimestamp = message.publishedAt;
        }
        
        return false;
      }
      
      return true;
    });
    
    const allMessages = [...filteredMessages];
    if (optimisticMessage) {
      const optimisticWithTimestamp = replacedMessageTimestamp !== undefined
        ? { ...optimisticMessage, publishedAt: replacedMessageTimestamp }
        : optimisticMessage;
      allMessages.push(optimisticWithTimestamp);
    }
    
    return allMessages.sort(sortMessages);
  }, [messages, optimisticMessage, workflowId]);
  
  const handleFileUpload = useCallback(async (file: File): Promise<{ success: boolean; data: any }> => {
    const result = await fileContext.handleFileUpload(file, workflowId || undefined);
    
    if (result.success && result.fileData) {
      const responseData = result.fileData;
      const fileData = responseData.file || responseData;
      const fileId = fileData?.id;
      
      if (fileId) {
        const newFile: WorkflowFile = {
          id: fileId,
          fileId: fileId,
          fileName: fileData.fileName || file.name,
          fileSize: fileData.fileSize || file.size,
          mimeType: fileData.mimeType || file.type || 'application/octet-stream',
          source: 'user_uploaded'
        };
        
        setPendingFiles(prev => {
          if (prev.some(f => f.fileId === fileId)) {
            return prev;
          }
          return [...prev, newFile];
        });
      }
    }
    
    return {
      success: result.success || false,
      data: result.fileData || null
    };
  }, [workflowId, fileContext]);

  const handleFileAttach = useCallback(async (fileId: string): Promise<void> => {
    const isInPending = pendingFiles.some(f => f.fileId === fileId);
    
    if (isInPending) {
      setPendingFiles(prev => prev.filter(f => f.fileId !== fileId));
    } else {
      let workflowFile: WorkflowFile | null = null;
      
      const userFile = fileContext.files.find(f => f.id === fileId);
      if (userFile) {
        workflowFile = {
          id: userFile.id,
          fileId: userFile.id,
          fileName: userFile.file_name,
          fileSize: userFile.size || 0,
          mimeType: userFile.mime_type || 'application/octet-stream',
          source: 'user_uploaded'
        };
      } else {
        const existingWorkflowFile = workflowFiles.find(f => f.fileId === fileId);
        if (existingWorkflowFile) {
          workflowFile = {
            ...existingWorkflowFile,
            id: existingWorkflowFile.id || existingWorkflowFile.fileId,
            fileId: existingWorkflowFile.fileId,
            fileName: existingWorkflowFile.fileName || 'Unknown File',
            fileSize: existingWorkflowFile.fileSize || 0,
            mimeType: existingWorkflowFile.mimeType || 'application/octet-stream',
            source: existingWorkflowFile.source || 'user_uploaded'
          };
        }
      }
      
      if (workflowFile) {
        setPendingFiles(prev => {
          if (prev.some(f => f.fileId === fileId)) {
            return prev;
          }
          return [...prev, workflowFile!];
        });
      }
    }
  }, [pendingFiles, fileContext.files, workflowFiles]);

  const handleFileUploadAndAttach = useCallback(async (file: File): Promise<{ success: boolean; data: any }> => {
    return await handleFileUpload(file);
  }, [handleFileUpload]);
  
  const handleFileRemove = useCallback(async (file: WorkflowFile) => {
    setPendingFiles(prev => prev.filter(f => f.fileId !== file.fileId));
  }, []);

  const handleFileDelete = useCallback(async (file: WorkflowFile) => {
    if (!file.fileId) return;
    
    const success = await fileContext.handleFileDelete(file.fileId, () => {
      setPendingFiles(prev => prev.filter(f => f.fileId !== file.fileId));
    });
    
    if (success) {
      setPendingFiles(prev => prev.filter(f => f.fileId !== file.fileId));
      
      if (workflowId) {
        const messagesWithFile = messages.filter((msg: WorkflowMessage) => {
          const docs = (msg as any).documents as MessageDocument[] | undefined;
          return docs?.some(doc => doc.fileId === file.fileId);
        });
        
        for (const message of messagesWithFile) {
          try {
            await deleteFileFromMessageApi(request, workflowId, message.id, file.fileId);
          } catch (error) {
          }
        }
      }
    }
  }, [workflowId, messages, fileContext, request]);

  // handleFileView is a no-op because ViewActionButton's ContentPreview handles the preview internally
  const handleFileView = useCallback(async (_file: WorkflowFile) => {
    // The ViewActionButton component handles the preview via ContentPreview
    // No additional action needed here
  }, []);

  const handleFileDownload = useCallback(async (file: WorkflowFile) => {
    if (!file.fileId) return;
    await fileContext.handleFileDownload(file.fileId, file.fileName);
  }, [fileContext]);
  
  const onInputChange = useCallback((value: string) => {
    setInputValue(value);
  }, []);
  
  // Separate stop handler - only stops the workflow without sending new input
  const handleStop = useCallback(async () => {
    if (!workflowId) return { success: false, error: 'No workflow to stop' };
    
    try {
      const result = await stopWorkflow();
      return result;
    } catch (error: any) {
      return { success: false, error: error.message || 'Failed to stop workflow' };
    }
  }, [workflowId, stopWorkflow]);
  
  const handleSubmit = useCallback(async () => {
    const trimmedInput = inputValue.trim();
    
    // If running and no new input, just stop
    if (isRunning && workflowId && !trimmedInput) {
      try {
        await stopWorkflow();
      } catch (error) {
        // Ignore stop errors
      }
      return;
    }
    
    // If running with new input, stop first then continue with new input
    if (isRunning && workflowId && trimmedInput) {
      try {
        // Stop the current workflow
        await stopWorkflow();
        // Continue below to send new input
      } catch (error) {
        // Ignore stop errors, try to continue anyway
      }
    }
    
    // No input and not running = nothing to do
    if (!trimmedInput || startingWorkflow) {
      return;
    }
    if (!trimmedInput || startingWorkflow) {
      return;
    }
    
    try {
      const filesToSend = pendingFiles.filter(file => file.fileId);
      const fileIdsToSend = filesToSend.map(f => f.fileId).filter((id): id is string => !!id);
      const sentFileIdsSet = new Set(fileIdsToSend);
      
      // Optimistically render user message immediately
      const optimisticMsg: WorkflowMessage = {
        id: `optimistic-${Date.now()}`,
        workflowId: workflowId || '',
        message: trimmedInput,
        role: 'user',
        publishedAt: Date.now(),
        documents: filesToSend.map(file => ({
          id: file.id || file.fileId,
          fileId: file.fileId,
          fileName: file.fileName,
          fileSize: file.fileSize,
          mimeType: file.mimeType,
          messageId: `optimistic-${Date.now()}`,
          roundNumber: 0,
          taskNumber: 0,
          actionNumber: 0,
          actionId: ''
        }))
      };
      setOptimisticMessage(optimisticMsg);
      
      // Optimistically update workflow status to 'running' immediately
      if (setWorkflowStatusOptimistic) {
        setWorkflowStatusOptimistic('running');
      }
      
      setPendingFiles(prev => prev.filter(file => 
        !file.fileId || !sentFileIdsSet.has(file.fileId)
      ));
      
      if (!chatWorkflowPermission || chatWorkflowPermission.create === 'n') {
        setOptimisticMessage(null);
        if (setWorkflowStatusOptimistic) {
          setWorkflowStatusOptimistic('idle');
        }
        return;
      }
      
      const selectedMode = workflowMode || 'Dynamic';
      const apiWorkflowMode: 'Dynamic' | 'Automation' = selectedMode;
      
      const workflowOptions: { workflowId?: string; workflowMode: 'Dynamic' | 'Automation' } = {
        workflowMode: apiWorkflowMode
      };
      
      if (workflowId) {
        workflowOptions.workflowId = workflowId;
      }
      
      const requestBody = {
        prompt: trimmedInput,
        listFileId: fileIdsToSend.length > 0 ? fileIdsToSend : undefined,
        userLanguage: 'en'
      };
      
      const result = await startWorkflow(requestBody, workflowOptions);
      
      if (result.success) {
        setInputValue('');
        
        const wasNewWorkflow = !workflowId;
        if (wasNewWorkflow && result.data) {
          const workflow = result.data as Workflow;
          
          // Dispatch event first to trigger refetch in useWorkflows
          window.dispatchEvent(new CustomEvent('workflowCreated', { 
            detail: { workflow } 
          }));
          
          // Refetch workflows list to ensure dropdown is updated
          await refetchWorkflows();
          
          // Update context first (this will trigger the sync effect to update lifecycle)
          selectWorkflowFromContext(workflow.id);
          
          // Also directly update lifecycle to ensure immediate state update
          await selectWorkflow(workflow.id);
        } else if (workflowId) {
          // For resumed workflows, ensure context is synced and update lifecycle
          selectWorkflowFromContext(workflowId);
          await selectWorkflow(workflowId);
        }
      } else {
        setOptimisticMessage(null);
        if (setWorkflowStatusOptimistic) {
          setWorkflowStatusOptimistic('idle');
        }
      }
    } catch (error) {
      setOptimisticMessage(null);
      if (setWorkflowStatusOptimistic) {
        setWorkflowStatusOptimistic('idle');
      }
    }
  }, [inputValue, pendingFiles, isRunning, workflowId, startingWorkflow, startWorkflow, stopWorkflow, resetWorkflow, refetchWorkflows, selectWorkflowFromContext, selectWorkflow, chatWorkflowPermission, workflowMode, setWorkflowStatusOptimistic]);

  useEffect(() => {
    const handleWorkflowCleared = () => {
      // Reset all workflow-related state
      setPendingFiles([]);
      setOptimisticMessage(null);
      // Reset workflow lifecycle state
      resetWorkflow();
      // Clear context selection
      clearWorkflowFromContext();
    };

    window.addEventListener('workflowCleared', handleWorkflowCleared);
    return () => {
      window.removeEventListener('workflowCleared', handleWorkflowCleared);
    };
  }, [resetWorkflow, clearWorkflowFromContext]);

  const handleWorkflowSelect = useCallback(async (item: { id: string | number; label: string; value: any; metadata?: Record<string, any> } | null) => {
    if (item === null) {
      clearWorkflowFromContext();
      resetWorkflow();
      setPendingFiles([]);
      setOptimisticMessage(null);
      return;
    }
    
    const workflowIdToSelect = typeof item.id === 'string' ? item.id : String(item.id);
    selectWorkflowFromContext(workflowIdToSelect);
    
    if (selectWorkflow) {
      await selectWorkflow(workflowIdToSelect);
    }
  }, [selectWorkflow, resetWorkflow, selectWorkflowFromContext, clearWorkflowFromContext]);
  
  const handlePromptSelect = useCallback(async (item: { id: string | number; label: string; value: any; metadata?: Record<string, any> } | null) => {
    if (item === null) {
      setSelectedPromptId(null);
      return;
    }
    
    const promptId = typeof item.id === 'string' ? item.id : String(item.id);
    
    if (!promptPermission || promptPermission.read === 'n') {
      return;
    }
    
    try {
      const prompt = await fetchPromptById(promptId);
      if (prompt && prompt.content) {
        setSelectedPromptId(promptId);
        setInputValue(prompt.content);
      }
    } catch (error: any) {
    }
  }, [fetchPromptById, promptPermission]);
  
  const handleWorkflowModeSelect = useCallback((item: { id: string | number; label: string; value: any; metadata?: Record<string, any> } | null) => {
    if (item === null) {
      setWorkflowMode(null);
      return;
    }
    
    const modeValue = item.value || item.id;
    const modeString = typeof modeValue === 'string' ? modeValue : String(modeValue);
    
    if (modeString === 'Dynamic' || modeString === 'Automation') {
      const mode = modeString as 'Dynamic' | 'Automation';
      setWorkflowMode(mode);
    }
  }, []);

  const workflowItems = useMemo(() => {
    console.log('🔄 useDashboardInputForm: Computing workflowItems from workflows:', workflows);
    
    if (!workflows || !Array.isArray(workflows)) {
      console.warn('⚠️ useDashboardInputForm: workflows is not an array:', workflows);
      return [];
    }
    
    if (workflows.length === 0) {
      console.log('ℹ️ useDashboardInputForm: workflows array is empty');
      return [];
    }
    
    const items = workflows.map(workflow => ({
      id: workflow.id,
      label: workflow.name || workflow.id,
      value: workflow,
      metadata: {
        status: workflow.status,
        workflowMode: workflow.workflowMode
      }
    }));
    
    console.log(`✅ useDashboardInputForm: Created ${items.length} workflow items:`, items);
    return items;
  }, [workflows]);
  
  const promptItems = useMemo(() => {
    if (!promptPermission || promptPermission.view === false || promptPermission.read === 'n') {
      return [];
    }
    return prompts.map(prompt => ({
      id: prompt.id,
      label: prompt.name || prompt.id,
      value: prompt,
      metadata: {
        content: prompt.content
      }
    }));
  }, [prompts, promptPermission]);
  
  const workflowModeItems = useMemo(() => [
    {
      id: 'Automation',
      label: 'Automation',
      value: 'Automation' as const,
      metadata: {
        description: 'Automated workflow processing'
      }
    },
    {
      id: 'Dynamic',
      label: 'Dynamic',
      value: 'Dynamic' as const,
      metadata: {
        description: 'Iterative dynamic-style processing'
      }
    }
  ], []);

  return {
    data: [],
    loading: false,
    error: null,
    inputValue,
    onInputChange,
    handleSubmit,
    handleStop,
    isSubmitting: startingWorkflow || isStopping,
    isStopping,
    workflowId: workflowId || undefined,
    workflowStatus,
    currentRound,
    isRunning,
    messages: displayMessages || [],
    logs: unifiedContentLogs || [], // Unified content logs (without operationId)
    dashboardTree, // Dashboard log tree (logs with operationId)
    onToggleOperationExpanded: toggleOperationExpanded,
    onToggleRoundExpanded: toggleRoundExpanded,
    getChildOperations,
    workflowItems,
    selectedWorkflowId: workflowId || selectedWorkflowId || null,
    onWorkflowSelect: handleWorkflowSelect,
    workflowsLoading,
    promptItems,
    selectedPromptId,
    onPromptSelect: handlePromptSelect,
    promptsLoading,
    promptPermission,
    workflowModeItems,
    selectedWorkflowMode: workflowMode,
    onWorkflowModeSelect: handleWorkflowModeSelect,
    playgroundUIPermission,
    chatWorkflowPermission,
    filePermission,
    workflowFiles,
    pendingFiles,
    handleFileUpload,
    handleFileDelete,
    handleFileRemove,
    handleFileView,
    uploadingFile: fileContext.uploadingFile,
    deletingFiles: fileContext.deletingFiles,
    previewingFiles: fileContext.previewingFiles,
    downloadingFiles: fileContext.downloadingFiles,
    handleFileDownload,
    isFileAttachmentPopupOpen,
    setIsFileAttachmentPopupOpen,
    allUserFiles: fileContext.files || [],
    handleFileAttach,
    handleFileUploadAndAttach,
    latestStats
  };
}

export function createDashboardHook() {
  return () => useDashboardInputForm();
}

