# frozen_string_literal: true

require "json"

module Common
  # Represents a Message object that is used in OpenAI Chat API requests
  # This object is referenced by both ChatRequester and ChatCompletion objects
  class Message
    # The keys that are used in the request body for messages
    MESSAGE_REQUEST_KEYS = %i[role content name tool_calls tool_call_id].freeze

    # The role of the author of this message.
    # One of: user, assistant, system
    # Default: system
    attr_reader :role

    # The contents of the message.
    attr_reader :content

    # Provides the model information to differentiate between participants of the same role.
    attr_reader :name

    # The tool calls generated by the model, such as function calls. (assistant msg only)
    attr_reader :tool_calls

    # Tool call that this message is responding to. (tool msg only)
    attr_reader :tool_call_id

    # Initializes the Message object
    #
    # @param [String, Hash] options The message content
    def initialize(options = {})
      if options.is_a?(String)
        @role = "system"
        @content = options
      else
        attributes_from_options(options)
      end
      json_content_parse
    end

    def json?
      !!@json_content
    end

    def empty?
      content.nil? || content.empty?
    end

    def to_h
      { role:, content:, name:, tool_calls:, tool_call_id: }.compact
    end

    private

    def attributes_from_options(options)
      @role = options[:role] || "system"
      @content = options[:content]
      @name = options[:name]
      @tool_calls = options[:tool_calls]
      @tool_call_id = options[:tool_call_id]
    end

    # Parses the content if it is a JSON string
    # This is used when the request is made with json: true flag
    # https://platform.openai.com/docs/guides/text-generation/json-mode
    def json_content_parse
      return unless @content.is_a?(String) && @content.start_with?("{", "[")

      @content = JSON.parse(@content, symbolize_names: true)
      @json_content = true
    rescue JSON::ParserError
      nil
    end
  end
end
