require 'faraday'

module Captain
  module Inter
    class AuthService
      API_BASE_URL = 'https://cdpj.partners.bancointer.com.br'.freeze
      TOKEN_URL = '/oauth/v2/token'.freeze

      def initialize(unit)
        @unit = unit
      end

      def token
        cached_token = Redis::Alfred.get(cache_key)
        return cached_token if cached_token.present?

        fetch_new_token
      end

      private

      def cache_key
        "inter_token:unit_#{@unit.id}"
      end

      def fetch_new_token
        raise "Unit #{@unit.name} is inactive" unless @unit.active?

        response = connection.post(TOKEN_URL) do |req|
          req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
          # Inter requires Basic Auth with ClientID:ClientSecret
          req.headers['Authorization'] = "Basic #{Base64.strict_encode64("#{@unit.inter_client_id}:#{@unit.inter_client_secret}")}"

          req.body = URI.encode_www_form({
                                           grant_type: 'client_credentials',
                                           scope: 'cob.write cob.read pix.write pix.read webhook.read webhook.write'
                                         })
        end

        raise "Auth Failed: #{response.body}" unless response.success?

        data = JSON.parse(response.body)
        access_token = data['access_token']
        expires_in = data['expires_in'].to_i

        # Cache with safety margin (5 min less than expiry)
        Redis::Alfred.setex(cache_key, access_token, expires_in - 300)

        access_token
      end

      def connection
        @connection ||= Faraday.new(url: API_BASE_URL) do |conn|
          conn.ssl[:client_cert] = OpenSSL::X509::Certificate.new(File.read(@unit.inter_cert_path))
          conn.ssl[:client_key] = OpenSSL::PKey::RSA.new(File.read(@unit.inter_key_path))
          conn.adapter Faraday.default_adapter
        end
      end
    end
  end
end
