# frozen_string_literal: true

require "json"
require "net/http"

require "provider/adapters/adapter"

class Provider
  module Adapters
    # Nepal Rastra Bank. Publishes daily buy/sell rates for 22 currencies
    # against NPR. Mid-market rate computed as average of buy and sell.
    # Rates with unit > 1 (e.g. JPY per 10) are normalized by dividing by unit.
    class NRB < Adapter
      BASE_URL = "https://www.nrb.org.np/api/forex/v1/rates"

      class << self
        def backfill_range = 90
      end

      def fetch(after: nil, upto: nil)
        end_date = upto || Date.today
        dataset = []
        page = 1

        loop do
          sleep(0.5) if page > 1
          url = URI(BASE_URL)
          url.query = URI.encode_www_form(
            from: after.to_s,
            to: end_date.to_s,
            page: page,
            per_page: 100,
          )

          response = Net::HTTP.get(url)
          data = JSON.parse(response)
          payload = data.dig("data", "payload") || []
          dataset.concat(parse(payload))

          pagination = data["pagination"] || {}
          break if page >= (pagination["pages"] || 1)

          page += 1
        end

        dataset
      end

      def parse(payload)
        payload = JSON.parse(payload) if payload.is_a?(String)
        return [] unless payload.is_a?(Array)

        payload.flat_map do |day|
          begin
            date = Date.parse(day["date"])
          rescue Date::Error
            next []
          end
          rates = day["rates"] || []

          rates.filter_map do |entry|
            iso = entry.dig("currency", "iso3")
            unit = Integer(entry.dig("currency", "unit") || 1)
            buy = entry["buy"]
            sell = entry["sell"]
            next unless buy && sell

            mid = (Float(buy) + Float(sell)) / 2.0
            rate = mid / unit
            next if rate.zero?

            { date:, base: iso, quote: "NPR", rate: }
          end
        end
      end
    end
  end
end
