import { ChatMessage } from '../../../types/chat';
import { GenericToolSchema, ParameterDefinition, StandardizedToolCall } from '../../../types/tool';
import { OpenRouterMessage, OpenRouterTool, OpenRouterToolCall, OpenRouterMessageContent } from './types';

export function convertMessages(messages: ChatMessage[]): OpenRouterMessage[] {
  return messages.map(msg => {
    let convertedMessage: Partial<OpenRouterMessage> = {
      content: msg.content,
    };

    switch (msg.role) {
      case 'system':
      case 'user':
      case 'assistant':
        convertedMessage.role = msg.role;
        break;
      case 'function':
        convertedMessage = {
          role: 'tool',
          content: msg.content,
        };
        break;
      default:
        console.warn(`Unknown role "${msg.role}" encountered. Treating as "user".`);
        convertedMessage.role = 'user';
    }

    if (msg.role === 'assistant' && (msg as any).function_call) {
      convertedMessage.tool_calls = [{
        id: (msg as any).function_call.name,
        type: 'function',
        function: {
          name: (msg as any).function_call.name,
          arguments: (msg as any).function_call.arguments,
        },
      }];
    }

    return convertedMessage as OpenRouterMessage;
  });
}

export function convertToolSchema(schema: GenericToolSchema): OpenRouterTool {
  return {
    type: 'function',
    function: {
      name: schema.name,
      description: schema.description,
      parameters: {
        type: 'object',
        properties: convertParameters(schema.parameters.properties),
        required: schema.parameters.required,
      },
    },
  };
}

export function convertParameters(params: Record<string, ParameterDefinition>): Record<string, ParameterDefinition> {
  const result: Record<string, ParameterDefinition> = {};
  for (const [key, value] of Object.entries(params)) {
    result[key] = convertParameterDefinition(value);
  }
  return result;
}

export function convertParameterDefinition(param: ParameterDefinition): ParameterDefinition {
  const result: ParameterDefinition = { type: param.type };
  if (param.description) result.description = param.description;
  if (param.enum) result.enum = param.enum;
  if (param.items) result.items = convertParameterDefinition(param.items);
  if (param.properties) result.properties = convertParameters(param.properties);
  if (param.required) result.required = param.required;
  return result;
}

export function convertToolCall(call: OpenRouterToolCall): StandardizedToolCall {
  try {
    const convertedCall = {
      name: call.function.name,
      arguments: JSON.parse(call.function.arguments),
    };
    validateToolCall(convertedCall);
    return convertedCall;
  } catch (error) {
    throw new Error(`Failed to convert tool call: ${error instanceof Error ? error.message : String(error)}`);
  }
}

export function validateToolCall(toolCall: StandardizedToolCall): void {
  if (typeof toolCall.name !== 'string' || toolCall.name.trim() === '') {
    throw new Error('Invalid tool call: name must be a non-empty string');
  }
  if (typeof toolCall.arguments !== 'object' || toolCall.arguments === null) {
    throw new Error('Invalid tool call: arguments must be an object');
  }
}

export function convertToolCalls(toolCalls: OpenRouterToolCall[] | undefined): StandardizedToolCall[] {
  if (!toolCalls || toolCalls.length === 0) return [];
  return toolCalls.map(call => {
    try {
      return convertToolCall(call);
    } catch (error) {
      console.error('Error converting tool call:', error);
      return null;
    }
  }).filter((call): call is StandardizedToolCall => call !== null);
}

export function extractToolCalls(message: OpenRouterMessage): StandardizedToolCall[] {
  if (!message.tool_calls || message.tool_calls.length === 0) {
    return [];
  }
  
  return message.tool_calls.map(toolCall => {
    try {
      return {
        name: toolCall.function.name,
        arguments: JSON.parse(toolCall.function.arguments),
      };
    } catch (error) {
      console.error('Error parsing tool call arguments:', error);
      return null;
    }
  }).filter((call): call is StandardizedToolCall => call !== null);
}