class FeatureModelMap < ApplicationRecord
  PROVIDER_MODEL_SEPARATOR = "::".freeze

  before_validation :set_provider, if: :should_infer_provider?

  validates :feature_name, presence: true, uniqueness: true
  validates :llm_model_name, presence: true
  validates :provider, presence: true
  validates :provider, inclusion: { in: ->(map) { map.class.available_providers } }

  LLM_PROVIDERS = {
    "OpenAI" => [
      { provider: "openai", model: "gpt-4o-mini" },
      { provider: "openai", model: "gpt-5.5" }
    ],
    "Vertex AI" => [
      { provider: "vertexai", model: "gemini-2.5-flash" },
      { provider: "vertexai", model: "gemini-3.1-pro-preview" },
      { provider: "vertexai", model: "gemini-embedding-001" }
    ],
    "OpenRouter" => [
      { provider: "openrouter", model: "google/gemini-2.5-flash" },
      { provider: "openrouter", model: "google/gemini-3.1-pro-preview-customtools" },
      { provider: "openrouter", model: "gemini-embedding-001" }
    ]
  }.freeze

  def self.grouped_llm_options
    LLM_PROVIDERS.map do |company, models|
      [company, models.map { |model_config| [model_config[:model], provider_model_value(model_config[:provider], model_config[:model])] }]
    end
  end

  def self.available_providers
    LLM_PROVIDERS.values.flatten.map { |model_config| model_config[:provider] }.uniq
  end

  def self.provider_model_value(provider, model)
    "#{provider}#{PROVIDER_MODEL_SEPARATOR}#{model}"
  end

  def self.provider_for_model(model)
    LLM_PROVIDERS.each_value do |models|
      match = models.find { |model_config| model_config[:model] == model }
      return match[:provider] if match
    end

    RubyLLM.models.find(model).provider
  rescue StandardError
    nil
  end

  def self.for_feature!(feature_name)
    find_by!(feature_name:)
  end

  def provider_model
    return if provider.blank? || llm_model_name.blank?

    self.class.provider_model_value(provider, llm_model_name)
  end

  def provider_model=(value)
    selected_provider, selected_model = value.to_s.split(PROVIDER_MODEL_SEPARATOR, 2)
    self.provider = selected_provider
    self.llm_model_name = selected_model
  end

  private

  def should_infer_provider?
    will_save_change_to_llm_model_name? && provider.blank?
  end

  def set_provider
    found_provider = self.class.provider_for_model(llm_model_name)
    self.provider = found_provider if found_provider
  end
end
