class RubyLLM::Providers::Anthropic

def api_base

def api_base
  'https://api.anthropic.com'
end

def build_payload(messages, tools:, temperature:, model:, stream: false)

def build_payload(messages, tools:, temperature:, model:, stream: false)
  {
    model: model,
    messages: format_messages(messages),
    temperature: temperature,
    stream: stream,
    max_tokens: RubyLLM.models.find(model).max_tokens
  }.tap do |payload|
    payload[:tools] = tools.values.map { |t| function_for(t) } if tools.any?
  end
end

def clean_parameters(parameters)

def clean_parameters(parameters)
  parameters.transform_values do |param|
    {
      type: param.type,
      description: param.description
    }.compact
  end
end

def completion_url

def completion_url
  '/v1/messages'
end

def convert_role(role)

def convert_role(role)
  case role
  when :tool then 'user'
  when :user then 'user'
  else 'assistant'
  end
end

def format_messages(messages)

def format_messages(messages)
  messages.map do |msg|
    if msg.tool_call?
      {
        role: 'assistant',
        content: [
          {
            type: 'text',
            text: msg.content
          },
          {
            type: 'tool_use',
            id: msg.tool_calls.values.first.id,
            name: msg.tool_calls.values.first.name,
            input: msg.tool_calls.values.first.arguments
          }
        ]
      }
    elsif msg.tool_result?
      {
        role: 'user',
        content: [
          {
            type: 'tool_result',
            tool_use_id: msg.tool_call_id,
            content: msg.content
          }
        ]
      }
    else
      {
        role: convert_role(msg.role),
        content: msg.content
      }
    end
  end
end

def function_for(tool)

def function_for(tool)
  {
    name: tool.name,
    description: tool.description,
    input_schema: {
      type: 'object',
      properties: clean_parameters(tool.parameters),
      required: required_parameters(tool.parameters)
    }
  }
end

def handle_stream(&block)

def handle_stream(&block)
  to_json_stream do |data|
    if data['type'] == 'content_block_delta' && data.dig('delta', 'type') == 'input_json_delta'
      block.call(
        Chunk.new(
          role: :assistant,
          model_id: data.dig('message', 'model'),
          content: data.dig('delta', 'text'),
          input_tokens: data.dig('message', 'usage', 'input_tokens'),
          output_tokens: data.dig('message', 'usage', 'output_tokens') || data.dig('usage', 'output_tokens'),
          tool_calls: { nil => ToolCall.new(id: nil, name: nil, arguments: data.dig('delta', 'partial_json')) }
        )
      )
    else
      block.call(
        Chunk.new(
          role: :assistant,
          model_id: data.dig('message', 'model'),
          content: data.dig('delta', 'text'),
          input_tokens: data.dig('message', 'usage', 'input_tokens'),
          output_tokens: data.dig('message', 'usage', 'output_tokens') || data.dig('usage', 'output_tokens'),
          tool_calls: parse_tool_calls(data['content_block'])
        )
      )
    end
  end
end

def headers

def headers
  {
    'x-api-key' => RubyLLM.config.anthropic_api_key,
    'anthropic-version' => '2023-06-01'
  }
end

def models_url

def models_url
  '/v1/models'
end

def parse_completion_response(response)

def parse_completion_response(response)
  data = response.body
  content_blocks = data['content'] || []
  text_blocks = content_blocks.select { |c| c['type'] == 'text' }
  text_content = text_blocks.map { |c| c['text'] }.join('')
  tool_use = content_blocks.find { |c| c['type'] == 'tool_use' }
  if tool_use
    Message.new(
      role: :assistant,
      content: text_content,
      tool_calls: parse_tool_calls(tool_use),
      input_tokens: data.dig('usage', 'input_tokens'),
      output_tokens: data.dig('usage', 'output_tokens'),
      model_id: data['model']
    )
  else
    Message.new(
      role: :assistant,
      content: text_content,
      input_tokens: data.dig('usage', 'input_tokens'),
      output_tokens: data.dig('usage', 'output_tokens'),
      model_id: data['model']
    )
  end
end

def parse_models_response(response)

def parse_models_response(response)
  capabilities = ModelCapabilities::Anthropic.new
  (response.body['data'] || []).map do |model|
    ModelInfo.new(
      id: model['id'],
      created_at: Time.parse(model['created_at']),
      display_name: model['display_name'],
      provider: 'anthropic',
      metadata: { type: model['type'] },
      context_window: capabilities.determine_context_window(model['id']),
      max_tokens: capabilities.determine_max_tokens(model['id']),
      supports_vision: capabilities.supports_vision?(model['id']),
      supports_functions: capabilities.supports_functions?(model['id']),
      supports_json_mode: capabilities.supports_json_mode?(model['id']),
      input_price_per_million: capabilities.get_input_price(model['id']),
      output_price_per_million: capabilities.get_output_price(model['id'])
    )
  end
end

def parse_tool_calls(content_block)

def parse_tool_calls(content_block)
  return nil unless content_block && content_block['type'] == 'tool_use'
  {
    content_block['id'] => ToolCall.new(
      id: content_block['id'],
      name: content_block['name'],
      arguments: content_block['input']
    )
  }
end

def required_parameters(parameters)

def required_parameters(parameters)
  parameters.select { |_, param| param.required }.keys
end