import { ApiRequestOptions } from '../hooks/useApi';

// ============================================================================
// TYPES & INTERFACES
// ============================================================================

// Workflow interfaces
export interface Workflow {
  id: string;
  mandateId: string;
  status: string;
  name?: string;
  workflowMode?: string;
  [key: string]: any; // Allow additional properties
}

export interface WorkflowMessage {
  [key: string]: any;
}

export interface WorkflowStats {
  [key: string]: any;
}

export interface WorkflowDocument {
  [key: string]: any;
}

export interface WorkflowLog {
  [key: string]: any;
}

// Request/Response interfaces based on API documentation
export interface FileAttachment {
  id: string;
  name: string;
}

export interface UserInputRequest {
  input: string;
  files?: FileAttachment[]; // optional file attachments - array of {id, name} objects
  metadata?: Record<string, any>; // optional metadata
}

export interface StartWorkflowRequest {
  prompt: string;
  listFileId?: string[]; // Array of file ID strings (files must be uploaded first via /api/files/upload)
  userLanguage?: string; // Optional, defaults to "en"
  metadata?: Record<string, any>;
}

export interface StartWorkflowResponse extends Workflow {
  // Workflow object returned from start endpoint
}

export interface ChatDataResponse {
  messages: WorkflowMessage[];
  logs: WorkflowLog[];
  stats: WorkflowStats[];
  documents: WorkflowDocument[];
}

// Type for the request function passed to API functions
export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<any>;

// ============================================================================
// API REQUEST FUNCTIONS
// ============================================================================

/**
 * Fetch all workflows for the current user
 * Endpoint: GET /api/workflows/
 */
export async function fetchWorkflows(request: ApiRequestFunction): Promise<Workflow[]> {
  console.log('📤 fetchWorkflows: Making API request to /api/workflows/');
  
  try {
    const data = await request({
      url: '/api/workflows/',
      method: 'get'
    });
    
    console.log('📥 fetchWorkflows: API response:', data);
    
    // Handle different response formats
    let workflows: Workflow[] = [];
    
    if (Array.isArray(data)) {
      // Direct array response
      workflows = data;
    } else if (data && typeof data === 'object') {
      // Check for common wrapper properties
      if (Array.isArray(data.workflows)) {
        workflows = data.workflows;
      } else if (Array.isArray(data.data)) {
        workflows = data.data;
      } else if (Array.isArray(data.items)) {
        workflows = data.items;
      } else if (Array.isArray(data.results)) {
        workflows = data.results;
      } else {
        // Try to find any array property
        const keys = Object.keys(data);
        for (const key of keys) {
          if (Array.isArray(data[key])) {
            workflows = data[key];
            console.log(`ℹ️ fetchWorkflows: Found workflows array in property '${key}'`);
            break;
          }
        }
      }
    }
    
    // Validate that we have workflow objects with id property
    const validWorkflows = workflows.filter((w: any) => w && typeof w === 'object' && w.id);
    
    if (validWorkflows.length !== workflows.length) {
      console.warn(`⚠️ fetchWorkflows: Filtered out ${workflows.length - validWorkflows.length} invalid workflows`);
    }
    
    console.log(`✅ fetchWorkflows: Returning ${validWorkflows.length} valid workflows`);
    return validWorkflows;
  } catch (error) {
    console.error('❌ fetchWorkflows: Error fetching workflows:', error);
    throw error;
  }
}

/**
 * Fetch a single workflow by ID
 * Endpoint: GET /api/workflows/{workflowId}
 */
export async function fetchWorkflow(
  request: ApiRequestFunction,
  workflowId: string
): Promise<Workflow & { messages?: WorkflowMessage[]; logs?: WorkflowLog[] }> {
  return await request({
    url: `/api/workflows/${workflowId}`,
    method: 'get'
  });
}

/**
 * Fetch workflow status (lightweight status check)
 * Endpoint: GET /api/workflows/{workflowId}/status
 */
export async function fetchWorkflowStatus(
  request: ApiRequestFunction,
  workflowId: string
): Promise<Workflow | { status: string } | null> {
    const data = await request({
    url: `/api/workflows/${workflowId}/status`,
    method: 'get'
  });
  
  if (data && typeof data === 'object') {
    if (data.status) {
      return { status: data.status };
    }
    return data;
  }
  
  return null;
}

/**
 * Fetch workflow messages
 * Endpoint: GET /api/workflows/{workflowId}/messages
 * Query params: messageId (optional) - fetch only newer messages
 */
export async function fetchWorkflowMessages(
  request: ApiRequestFunction,
  workflowId: string,
  messageId?: string
): Promise<WorkflowMessage[]> {
  const params = messageId ? { messageId } : undefined;
    const data = await request({
    url: `/api/workflows/${workflowId}/messages`,
    method: 'get',
    params
  });
  
  if (Array.isArray(data)) {
    return data;
  }
  
  if (data && typeof data === 'object') {
    if (Array.isArray(data.messages)) {
      return data.messages;
    }
    if (Array.isArray(data.data)) {
      return data.data;
    }
  }
  
  return [];
}

/**
 * Fetch workflow logs
 * Endpoint: GET /api/workflows/{workflowId}/logs
 * Query params: logId (optional) - fetch only newer logs
 */
export async function fetchWorkflowLogs(
  request: ApiRequestFunction,
  workflowId: string,
  logId?: string
): Promise<WorkflowLog[]> {
  const params = logId ? { logId } : undefined;
    const data = await request({
    url: `/api/workflows/${workflowId}/logs`,
    method: 'get',
    params
  });
  
  if (Array.isArray(data)) {
    return data;
  }
  
  if (data && typeof data === 'object') {
    if (Array.isArray(data.logs)) {
      return data.logs;
    }
    if (Array.isArray(data.data)) {
      return data.data;
    }
  }
  
  return [];
}

/**
 * Fetch unified chat data (messages, logs, stats, documents)
 * Endpoint: GET /api/chat/playground/{workflowId}/chatData
 * Query params: afterTimestamp (optional) - fetch only data created after this time
 */
export async function fetchChatData(
  request: ApiRequestFunction,
  workflowId: string,
  afterTimestamp?: number
): Promise<ChatDataResponse> {
  const params = afterTimestamp ? { afterTimestamp: afterTimestamp.toString() } : undefined;
  const requestConfig = {
    url: `/api/chat/playground/${workflowId}/chatData`,
    method: 'get' as const,
    params
  };
  
  console.log('📤 fetchChatData request:', requestConfig);
  
    const data = await request(requestConfig);
  
  console.log('📥 fetchChatData response:', data);
  
  // Handle unified items format: { items: [{ type: 'message'|'log'|'stat', item: {...}, createdAt: ... }] }
  if (data.items && Array.isArray(data.items)) {
    const messages: WorkflowMessage[] = [];
    const logs: WorkflowLog[] = [];
    const stats: WorkflowStats[] = [];
    const documents: WorkflowDocument[] = [];
    
    data.items.forEach((item: any) => {
      if (item.type === 'message') {
        // Handle both formats: item.item or direct item data
        const messageData = item.item || item;
        if (messageData && (messageData.id || messageData.message)) {
          messages.push(messageData);
        } else {
          console.warn('⚠️ Invalid message item:', item);
        }
      } else if (item.type === 'log') {
        const logData = item.item || item;
        if (logData) {
          logs.push(logData);
        }
      } else if (item.type === 'stat') {
        const statData = item.item || item;
        if (statData) {
          stats.push(statData);
        }
      }
      // Documents might be in items or separate
      if (item.type === 'document') {
        const docData = item.item || item;
        if (docData) {
          documents.push(docData);
        }
      }
    });
    
    console.log('📦 Extracted from items:', {
      messages: messages.length,
      logs: logs.length,
      stats: stats.length,
      documents: documents.length
    });
    
    return {
      messages,
      logs,
      stats,
      documents: documents.length > 0 ? documents : (Array.isArray(data.documents) ? data.documents : [])
    };
  }
  
  // Fallback to direct format: { messages: [], logs: [], stats: [] }
  return {
    messages: Array.isArray(data.messages) ? data.messages : [],
    logs: Array.isArray(data.logs) ? data.logs : [],
    stats: Array.isArray(data.stats) ? data.stats : [],
    documents: Array.isArray(data.documents) ? data.documents : []
  };
}

/**
 * Start a new workflow or continue an existing one
 * Endpoint: POST /api/chat/playground/start
 * Query params: workflowId (optional), workflowMode (default: "Actionplan")
 */
export async function startWorkflowApi(
  request: ApiRequestFunction,
  workflowData: StartWorkflowRequest,
  options?: { workflowId?: string; workflowMode?: 'Dynamic' | 'Automation' }
): Promise<StartWorkflowResponse> {
  const params: Record<string, string> = {};
  
  // workflowMode is REQUIRED according to API spec
  if (options?.workflowMode) {
    params.workflowMode = options.workflowMode;
  } else {
    // Default to 'Dynamic' if not provided (though it should always be provided)
    params.workflowMode = 'Dynamic';
  }
  
  if (options?.workflowId) {
    params.workflowId = options.workflowId;
  }
  
  // Request body uses 'prompt' field (not 'input') according to API spec
  const requestBody: any = {
    prompt: workflowData.prompt,
    ...(workflowData.listFileId && workflowData.listFileId.length > 0 && { listFileId: workflowData.listFileId }),
    ...(workflowData.userLanguage && { userLanguage: workflowData.userLanguage }),
    ...(workflowData.metadata && { metadata: workflowData.metadata })
  };
  
  const requestConfig = {
    url: '/api/chat/playground/start',
    method: 'post' as const,
    data: requestBody,
    params: params // Always include workflowMode
  };
  
  // Log full request details
  console.log('📤 Full startWorkflow request details:');
  console.log('  URL:', requestConfig.url);
  console.log('  Method:', requestConfig.method);
  console.log('  Query Parameters:', params);
  console.log('  Request Body:', JSON.stringify(requestBody, null, 2));
  console.log('  Full Request Config:', JSON.stringify(requestConfig, null, 2));
  
  const response = await request(requestConfig);
  
  console.log('📥 startWorkflow response:', response);
  
  return response;
}

/**
 * Stop a running workflow
 * Endpoint: POST /api/chat/playground/{workflowId}/stop
 */
export async function stopWorkflowApi(
  request: ApiRequestFunction,
  workflowId: string
): Promise<void> {
  await request({
    url: `/api/chat/playground/${workflowId}/stop`,
    method: 'post'
  });
}

/**
 * Update workflow properties
 * Endpoint: PUT /api/workflows/{workflowId}
 */
export async function updateWorkflowApi(
  request: ApiRequestFunction,
  workflowId: string,
  updateData: Partial<{ name: string; description?: string; tags?: string[] }>
): Promise<Workflow> {
  return await request({
    url: `/api/workflows/${workflowId}`,
    method: 'put',
    data: updateData
  });
}

/**
 * Delete a workflow and all associated data
 * Endpoint: DELETE /api/workflows/{workflowId}
 */
export async function deleteWorkflowApi(
  request: ApiRequestFunction,
  workflowId: string
): Promise<void> {
  await request({
    url: `/api/workflows/${workflowId}`,
    method: 'delete'
  });
}

/**
 * Delete multiple workflows
 */
export async function deleteWorkflowsApi(
  request: ApiRequestFunction,
  workflowIds: string[]
): Promise<void> {
  // Delete workflows one by one since there's no bulk delete endpoint
  const deletePromises = workflowIds.map(workflowId =>
    request({
      url: `/api/workflows/${workflowId}`,
      method: 'delete'
    }).catch(error => {
      console.error(`Failed to delete workflow ${workflowId}:`, error);
      throw error;
    })
  );
  
  await Promise.all(deletePromises);
}

/**
 * Delete a message from a workflow
 * Endpoint: DELETE /api/workflows/{workflowId}/messages/{messageId}
 */
export async function deleteMessageApi(
  request: ApiRequestFunction,
  workflowId: string,
  messageId: string
): Promise<void> {
  await request({
    url: `/api/workflows/${workflowId}/messages/${messageId}`,
    method: 'delete'
  });
}

/**
 * Delete a file reference from a message
 * Endpoint: DELETE /api/workflows/{workflowId}/messages/{messageId}/files/{fileId}
 */
export async function deleteFileFromMessageApi(
  request: ApiRequestFunction,
  workflowId: string,
  messageId: string,
  fileId: string
): Promise<void> {
  await request({
    url: `/api/workflows/${workflowId}/messages/${messageId}/files/${fileId}`,
    method: 'delete'
  });
}

/**
 * Fetch attributes for a workflow type
 * Endpoint: GET /api/attributes/{entityType}
 */
export interface AttributeDefinition {
  name: string;
  type: 'text' | 'email' | 'date' | 'checkbox' | 'select' | 'multiselect' | 'number' | 'textarea';
  label: string;
  description?: string;
  required?: boolean;
  default?: any;
  options?: Array<{ value: string | number; label: string | { [key: string]: string } }> | string;
  validation?: any;
  ui?: any;
  readonly?: boolean;
  editable?: boolean;
  visible?: boolean;
  order?: number;
  placeholder?: string;
  sortable?: boolean;
  filterable?: boolean;
  searchable?: boolean;
  width?: number;
  minWidth?: number;
  maxWidth?: number;
  filterOptions?: string[];
}

export async function fetchAttributes(
  request: ApiRequestFunction,
  entityType: string = 'ChatWorkflow'
): Promise<AttributeDefinition[]> {
    const data = await request({
    url: `/api/attributes/${entityType}`,
    method: 'get'
  });
  
  // Extract attributes from response - check if response.data.attributes exists, otherwise check if response.data is an array
  let attrs: AttributeDefinition[] = [];
  if (data?.attributes && Array.isArray(data.attributes)) {
    attrs = data.attributes;
  } else if (Array.isArray(data)) {
    attrs = data;
  } else if (data && typeof data === 'object') {
    // Try to find any array property in the response
    const keys = Object.keys(data);
    for (const key of keys) {
      if (Array.isArray(data[key])) {
        attrs = data[key];
        break;
      }
    }
  }
  
  return attrs;
}

