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>;
  allowedProviders?: string[]; // Optional: Restrict AI calls to these providers (empty = all RBAC-permitted)
}

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

export interface ChatDataResponse {
  messages: WorkflowMessage[];
  logs: WorkflowLog[];
  documents: WorkflowDocument[];
  workflowCost: number;
}

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

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

function _requireApiBaseUrl(apiBaseUrl: string | undefined, caller: string): string {
  if (!apiBaseUrl) {
    throw new Error(`${caller}: apiBaseUrl is required (instanceId/featureCode missing)`);
  }
  return apiBaseUrl;
}

/**
 * Fetch workflows - feature-scoped: GET {apiBaseUrl}/workflows
 */
export async function fetchWorkflows(
  request: ApiRequestFunction,
  params?: { pagination?: string },
  apiBaseUrl?: string
): Promise<Workflow[] | { items: Workflow[]; pagination?: any }> {
  const base = _requireApiBaseUrl(apiBaseUrl, 'fetchWorkflows');
  const url = `${base}/workflows`;
  console.log('📤 fetchWorkflows: Making API request to', url);
  
  try {
    const requestConfig: any = { url, method: 'get' as const };
    if (params?.pagination) {
      requestConfig.params = { pagination: params.pagination };
    }
    const data = await request(requestConfig);
    
    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: GET {apiBaseUrl}/workflows/{workflowId}
 */
export async function fetchWorkflow(
  request: ApiRequestFunction,
  workflowId: string,
  apiBaseUrl?: string
): Promise<Workflow & { messages?: WorkflowMessage[]; logs?: WorkflowLog[] }> {
  const base = _requireApiBaseUrl(apiBaseUrl, 'fetchWorkflow');
  const url = `${base}/workflows/${workflowId}`;
  return await request({ url, method: 'get' });
}

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

/**
 * Fetch workflow messages: GET {apiBaseUrl}/workflows/{workflowId}/messages
 */
export async function fetchWorkflowMessages(
  request: ApiRequestFunction,
  workflowId: string,
  messageId?: string,
  apiBaseUrl?: string
): Promise<WorkflowMessage[]> {
  const params = messageId ? { messageId } : undefined;
  const base = _requireApiBaseUrl(apiBaseUrl, 'fetchWorkflowMessages');
  const url = `${base}/workflows/${workflowId}/messages`;
  const data = await request({ url, 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: GET {apiBaseUrl}/workflows/{workflowId}/logs
 */
export async function fetchWorkflowLogs(
  request: ApiRequestFunction,
  workflowId: string,
  logId?: string,
  apiBaseUrl?: string
): Promise<WorkflowLog[]> {
  const params = logId ? { logId } : undefined;
  const base = _requireApiBaseUrl(apiBaseUrl, 'fetchWorkflowLogs');
  const url = `${base}/workflows/${workflowId}/logs`;
  const data = await request({ url, 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/automations/{instanceId}/workflows/{workflowId}/chatData
 * Query params: afterTimestamp (optional) - fetch only data created after this time
 */
export async function fetchChatData(
  request: ApiRequestFunction,
  instanceId: string,
  workflowId: string,
  afterTimestamp?: number
): Promise<ChatDataResponse> {
  const params = afterTimestamp ? { afterTimestamp: afterTimestamp.toString() } : undefined;
  const requestConfig = {
    url: `/api/automations/${instanceId}/workflows/${workflowId}/chatData`,
    method: 'get' as const,
    params
  };
  
  console.log('📤 fetchChatData request:', requestConfig);
  
    const data = await request(requestConfig);
  
  console.log('📥 fetchChatData response:', data);
  
  const workflowCost: number = data.workflowCost ?? 0;
  
  if (data.items && Array.isArray(data.items)) {
    const messages: WorkflowMessage[] = [];
    const logs: WorkflowLog[] = [];
    const documents: WorkflowDocument[] = [];
    
    data.items.forEach((item: any) => {
      if (item.type === 'message') {
        const messageData = item.item || item;
        if (messageData && (messageData.id || messageData.message)) {
          messages.push(messageData);
        }
      } else if (item.type === 'log') {
        const logData = item.item || item;
        if (logData) {
          logs.push(logData);
        }
      } else if (item.type === 'document') {
        const docData = item.item || item;
        if (docData) {
          documents.push(docData);
        }
      }
    });
    
    return {
      messages,
      logs,
      documents: documents.length > 0 ? documents : (Array.isArray(data.documents) ? data.documents : []),
      workflowCost
    };
  }
  
  return {
    messages: Array.isArray(data.messages) ? data.messages : [],
    logs: Array.isArray(data.logs) ? data.logs : [],
    documents: Array.isArray(data.documents) ? data.documents : [],
    workflowCost
  };
}

/**
 * Start a new workflow or continue an existing one
 * Endpoint: POST /api/automations/{instanceId}/start
 * Query params: workflowId (optional), workflowMode (default: "Dynamic")
 */
export async function startWorkflowApi(
  request: ApiRequestFunction,
  instanceId: string,
  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 {
    params.workflowMode = 'Dynamic';
  }
  
  if (options?.workflowId) {
    params.workflowId = options.workflowId;
  }
  
  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 }),
    ...(workflowData.allowedProviders && workflowData.allowedProviders.length > 0 && { allowedProviders: workflowData.allowedProviders })
  };
  
  const requestConfig = {
    url: `/api/automations/${instanceId}/start`,
    method: 'post' as const,
    data: requestBody,
    params: params
  };
  
  // 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/automations/{instanceId}/workflows/{workflowId}/stop
 */
export async function stopWorkflowApi(
  request: ApiRequestFunction,
  instanceId: string,
  workflowId: string
): Promise<void> {
  await request({
    url: `/api/automations/${instanceId}/workflows/${workflowId}/stop`,
    method: 'post'
  });
}

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

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

/**
 * Delete multiple workflows: DELETE {apiBaseUrl}/workflows/{workflowId} (per workflow)
 */
export async function deleteWorkflowsApi(
  request: ApiRequestFunction,
  workflowIds: string[],
  apiBaseUrl?: string
): Promise<void> {
  const base = `${_requireApiBaseUrl(apiBaseUrl, 'deleteWorkflowsApi')}/workflows`;
  const deletePromises = workflowIds.map(workflowId =>
    request({
      url: `${base}/${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: DELETE {apiBaseUrl}/workflows/{workflowId}/messages/{messageId}
 */
export async function deleteMessageApi(
  request: ApiRequestFunction,
  workflowId: string,
  messageId: string,
  apiBaseUrl?: string
): Promise<void> {
  const base = _requireApiBaseUrl(apiBaseUrl, 'deleteMessageApi');
  const url = `${base}/workflows/${workflowId}/messages/${messageId}`;
  await request({ url, method: 'delete' });
}

/**
 * Delete a file reference from a message: DELETE {apiBaseUrl}/workflows/{workflowId}/messages/{messageId}/files/{fileId}
 */
export async function deleteFileFromMessageApi(
  request: ApiRequestFunction,
  workflowId: string,
  messageId: string,
  fileId: string,
  apiBaseUrl?: string
): Promise<void> {
  const base = _requireApiBaseUrl(apiBaseUrl, 'deleteFileFromMessageApi');
  const url = `${base}/workflows/${workflowId}/messages/${messageId}/files/${fileId}`;
  await request({ url, 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;
}

