# frozen_string_literal: true

# Language Model
class LanguageModel
  class InvalidAIResponseError < StandardError; end

  # Used for Q&A
  def self.stream_with_system_prompt(text, prompt, channel, language_model = "gpt-4o-mini", temperature: 0.0)
    client = OpenAI::Client.new

    lm = language_model

    Rails.logger.fatal("[LLM]  Sending chat")

    client.chat(
      parameters: {
        model: lm,
        messages: [{ "role": "user", "content": text }, { role: "system", content: prompt }],
        temperature:,
        stream: proc do |chunk, _bytesize|
          stream_chunk = { chunk: }
          Rails.logger.fatal("STREAM CHUNK #{stream_chunk} to #{channel}")
          # QuestionsChannel.send_data(channel, stream_chunk)
        end
      }
    )
  end

  def self.append_to_prompt(text, prompt)
    "#{prompt.prompt}\n#{text}"
  end

  def self.send_with_system_prompt_v2(text, prompt, return_json: false, temperature: 0, language_model: "gpt-4o-mini", provider: "openai")
    chat = RubyLLM.chat(provider:, model: language_model)
    chat.with_instructions(prompt)
    { data: chat.ask(text)&.content || "", status: "ok" }
  end

  def self.send_with_system_prompt(text, prompt, return_json: false, temperature: nil, language_model: "gpt-4o-mini")
    lm = language_model
    Rails.logger.fatal("Model is #{lm}")
    content = {
      model: lm,
      messages: [{ role: "system", content: prompt }, { "role": "user", "content": text }]
    }

    content[:temperature] = 0.0
    content[:temperature] = temperature if temperature

    content[:response_format] = { type: "json_object" } if return_json

    res = HTTP.auth("Bearer #{Rails.application.credentials.openai_secret}")
              .post("https://api.openai.com/v1/chat/completions", json: content)
    # Rails.logger.fatal(res.to_s)
    begin
      { status: "ok", data: JSON.parse(res.to_s)["choices"][0]["message"]["content"] }
    rescue StandardError => e
      Rails.logger.fatal "Error retrieving response #{e.inspect} #{res}"
      { status: "error" }
    end
  end

  def self.translated_chunk_valid?(original_chunk, translated_chunk, manual)
    return false unless translated_chunk.is_a?(Array) && translated_chunk.size == original_chunk.size

    key = manual ? "index" : "start"

    original_chunk.zip(translated_chunk).all? do |original, translated|
      translated.is_a?(Hash) && original[key] == translated[key]
    end
  end
end
