import { Mem0Icon } from '@/components/icons'
import { AuthMode, type BlockConfig } from '@/blocks/types'
import type { Mem0Response } from '@/tools/mem0/types'

export const Mem0Block: BlockConfig<Mem0Response> = {
  type: 'mem0',
  name: 'Mem0',
  description: 'Agent memory management',
  authMode: AuthMode.ApiKey,
  longDescription: 'Integrate Mem0 into the workflow. Can add, search, and retrieve memories.',
  bgColor: '#181C1E',
  icon: Mem0Icon,
  category: 'tools',
  docsLink: 'https://docs.sim.ai/tools/mem0',
  subBlocks: [
    {
      id: 'operation',
      title: 'Operation',
      type: 'dropdown',
      options: [
        { label: 'Add Memories', id: 'add' },
        { label: 'Search Memories', id: 'search' },
        { label: 'Get Memories', id: 'get' },
      ],
      placeholder: 'Select an operation',
      value: () => 'add',
    },
    {
      id: 'userId',
      title: 'User ID',
      type: 'short-input',
      placeholder: 'Enter user identifier',
      value: () => 'userid', // Default to the working user ID from curl example
      required: true,
    },
    {
      id: 'messages',
      title: 'Messages',
      type: 'code',
      placeholder: 'JSON array, e.g. [{"role": "user", "content": "I love Sim!"}]',
      language: 'json',
      condition: {
        field: 'operation',
        value: 'add',
      },
      required: true,
    },
    {
      id: 'query',
      title: 'Search Query',
      type: 'long-input',
      placeholder: 'Enter search query to find relevant memories',
      condition: {
        field: 'operation',
        value: 'search',
      },
      required: true,
    },
    {
      id: 'memoryId',
      title: 'Memory ID',
      type: 'short-input',
      placeholder: 'Specific memory ID to retrieve',
      condition: {
        field: 'operation',
        value: 'get',
      },
    },
    {
      id: 'startDate',
      title: 'Start Date',
      type: 'short-input',
      placeholder: 'YYYY-MM-DD',
      condition: {
        field: 'operation',
        value: 'get',
      },
      wandConfig: {
        enabled: true,
        prompt: `Generate a date in YYYY-MM-DD format based on the user's description.
Examples:
- "last week" -> Calculate 7 days ago
- "beginning of this month" -> First day of current month
- "30 days ago" -> Calculate 30 days ago
- "start of year" -> January 1 of current year

Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`,
        placeholder: 'Describe the start date (e.g., "last week", "30 days ago")...',
        generationType: 'timestamp',
      },
    },
    {
      id: 'endDate',
      title: 'End Date',
      type: 'short-input',
      placeholder: 'YYYY-MM-DD',
      condition: {
        field: 'operation',
        value: 'get',
      },
      wandConfig: {
        enabled: true,
        prompt: `Generate a date in YYYY-MM-DD format based on the user's description.
Examples:
- "today" -> Today's date
- "yesterday" -> Yesterday's date
- "end of last week" -> Last Sunday's date
- "now" -> Today's date

Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, no extra text.`,
        placeholder: 'Describe the end date (e.g., "today", "yesterday")...',
        generationType: 'timestamp',
      },
    },
    {
      id: 'apiKey',
      title: 'API Key',
      type: 'short-input',
      placeholder: 'Enter your Mem0 API key',
      password: true,
      required: true,
    },
    {
      id: 'limit',
      title: 'Result Limit',
      type: 'slider',
      min: 1,
      max: 50,
      step: 1,
      integer: true,
      condition: {
        field: 'operation',
        value: ['search', 'get'],
      },
    },
  ],
  tools: {
    access: ['mem0_add_memories', 'mem0_search_memories', 'mem0_get_memories'],
    config: {
      tool: (params: Record<string, any>) => {
        const operation = params.operation || 'add'
        switch (operation) {
          case 'add':
            return 'mem0_add_memories'
          case 'search':
            return 'mem0_search_memories'
          case 'get':
            return 'mem0_get_memories'
          default:
            return 'mem0_add_memories'
        }
      },
      params: (params: Record<string, any>) => {
        // Create detailed error information for any missing required fields
        const errors: string[] = []

        // Validate required API key for all operations
        if (!params.apiKey) {
          errors.push('API Key is required')
        }

        // For search operation, validate required fields
        if (params.operation === 'search') {
          if (!params.query || params.query.trim() === '') {
            errors.push('Search Query is required')
          }

          if (!params.userId) {
            errors.push('User ID is required')
          }
        }

        // For add operation, validate required fields
        if (params.operation === 'add') {
          if (!params.messages) {
            errors.push('Messages are required for add operation')
          } else if (!Array.isArray(params.messages) || params.messages.length === 0) {
            errors.push('Messages must be a non-empty array')
          } else {
            for (const msg of params.messages) {
              if (!msg.role || !msg.content) {
                errors.push("Each message must have 'role' and 'content' properties")
                break
              }
            }
          }

          if (!params.userId) {
            errors.push('User ID is required')
          }
        }

        // Throw error if any required fields are missing
        if (errors.length > 0) {
          throw new Error(`Mem0 Block Error: ${errors.join(', ')}`)
        }

        const result: Record<string, any> = {
          apiKey: params.apiKey,
        }

        // Add any identifiers that are present
        if (params.userId) result.userId = params.userId

        // Add version if specified
        if (params.version) result.version = params.version

        if (params.limit) result.limit = params.limit

        const operation = params.operation || 'add'

        // Process operation-specific parameters
        switch (operation) {
          case 'add':
            if (params.messages) {
              try {
                // Ensure messages are properly formatted
                const messagesArray =
                  typeof params.messages === 'string'
                    ? JSON.parse(params.messages)
                    : params.messages

                // Validate message structure
                if (Array.isArray(messagesArray) && messagesArray.length > 0) {
                  let validMessages = true
                  for (const msg of messagesArray) {
                    if (!msg.role || !msg.content) {
                      validMessages = false
                      break
                    }
                  }
                  if (validMessages) {
                    result.messages = messagesArray
                  } else {
                    // Consistent with other error handling - collect in errors array
                    errors.push('Invalid message format - each message must have role and content')
                    throw new Error(
                      'Mem0 Block Error: Invalid message format - each message must have role and content'
                    )
                  }
                } else {
                  // Consistent with other error handling
                  errors.push('Messages must be a non-empty array')
                  throw new Error('Mem0 Block Error: Messages must be a non-empty array')
                }
              } catch (e: any) {
                if (!errors.includes('Messages must be valid JSON')) {
                  errors.push('Messages must be valid JSON')
                }
                throw new Error(`Mem0 Block Error: ${e.message || 'Messages must be valid JSON'}`)
              }
            }
            break
          case 'search':
            if (params.query) {
              result.query = params.query

              // Check if we have at least one identifier for search
              if (!params.userId) {
                errors.push('Search requires a User ID')
                throw new Error('Mem0 Block Error: Search requires a User ID')
              }
            } else {
              errors.push('Search requires a query parameter')
              throw new Error('Mem0 Block Error: Search requires a query parameter')
            }

            // Include limit if specified
            if (params.limit) {
              result.limit = Number(params.limit)
            }
            break
          case 'get':
            if (params.memoryId) {
              result.memoryId = params.memoryId
            }

            // Add date range filtering for v2 get memories
            if (params.startDate) {
              result.startDate = params.startDate
            }

            if (params.endDate) {
              result.endDate = params.endDate
            }
            break
        }

        return result
      },
    },
  },
  inputs: {
    operation: { type: 'string', description: 'Operation to perform' },
    apiKey: { type: 'string', description: 'Mem0 API key' },
    userId: { type: 'string', description: 'User identifier' },
    version: { type: 'string', description: 'API version' },
    messages: { type: 'json', description: 'Message data array' },
    query: { type: 'string', description: 'Search query' },
    memoryId: { type: 'string', description: 'Memory identifier' },
    startDate: { type: 'string', description: 'Start date filter' },
    endDate: { type: 'string', description: 'End date filter' },
    limit: { type: 'number', description: 'Result limit' },
  },
  outputs: {
    ids: { type: 'json', description: 'Memory identifiers' },
    memories: { type: 'json', description: 'Memory data' },
    searchResults: { type: 'json', description: 'Search results' },
  },
}
