# frozen_string_literal: true

class Api::V1::DonationCampaignsController < Api::BaseController
  before_action :require_user!

  STOPLIGHT_COOL_OFF_TIME = 60
  STOPLIGHT_FAILURE_THRESHOLD = 10

  def index
    return head 204 if api_url.blank?

    json = from_cache
    return render json: json if json.present?

    campaign = fetch_campaign
    return head 204 if campaign.nil?

    save_to_cache!(campaign)

    render json: campaign
  end

  private

  def api_url
    Rails.configuration.x.donation_campaigns.api_url
  end

  def seed
    @seed ||= Random.new(current_account.id).rand(100)
  end

  def from_cache
    key = Rails.cache.read(request_key, raw: true)
    return if key.blank?

    campaign = Rails.cache.read("donation_campaign:#{key}", raw: true)
    JSON.parse(campaign) if campaign.present?
  end

  def save_to_cache!(campaign)
    return if campaign.blank?

    Rails.cache.write_multi(
      {
        request_key => campaign_key(campaign),
        "donation_campaign:#{campaign_key(campaign)}" => campaign.to_json,
      },
      expires_in: 1.hour,
      raw: true
    )
  end

  def fetch_campaign
    stoplight_wrapper.run do
      url = Addressable::URI.parse(api_url)
      url.query_values = { platform: 'web', seed: seed, locale: locale, environment: Rails.configuration.x.donation_campaigns.environment }.compact

      Request.new(:get, url.to_s).perform do |res|
        return JSON.parse(res.body_with_limit) if res.code == 200
      end
    end
  rescue *Mastodon::HTTP_CONNECTION_ERRORS, JSON::ParserError
    nil
  end

  def stoplight_wrapper
    Stoplight(
      'donation_campaigns',
      cool_off_time: STOPLIGHT_COOL_OFF_TIME,
      threshold: STOPLIGHT_FAILURE_THRESHOLD
    )
  end

  def request_key
    "donation_campaign_request:#{seed}:#{locale}"
  end

  def campaign_key(campaign)
    "#{campaign['id']}:#{campaign['locale']}"
  end

  def locale
    I18n.locale.to_s
  end
end
