module Util::Wechat
  BASE_SITE = 'https://api.weixin.qq.com'.freeze

  Error = Class.new(StandardError)

  class << self
    attr_accessor :appid, :secret

    def js_sdk_signature(url, noncestr, timestamp)
      data = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }
      str = data.map { |k, v| "#{k}=#{v}" }.join('&')
      Digest::SHA1.hexdigest(str)
    end

    def access_token
      # 7200s 有效时间
      Rails.cache.fetch(access_token_cache_key, expires_in: 100.minutes) do
        result = request(:get, '/cgi-bin/token', appid: appid, secret: secret, grant_type: 'client_credential')
        result['access_token']
      end
    end

    def refresh_access_token
      Rails.cache.delete(access_token_cache_key)
      access_token
    end

    def jsapi_ticket
      # 7200s 有效时间
      Rails.cache.fetch(jsapi_ticket_cache_key, expires_in: 100.minutes) do
        result = request(:get, '/cgi-bin/ticket/getticket', access_token: access_token, type: 'jsapi')
        result['ticket']
      end
    end

    def refresh_jsapi_ticket
      Rails.cache.delete(jsapi_ticket_cache_key)
      jsapi_ticket
    end

    def access_token_cache_key
      "#{base_cache_key}/access_token"
    end

    def jsapi_ticket_cache_key
      "#{base_cache_key}/jsapi_ticket"
    end

    def base_cache_key
      "wechat/#{appid}"
    end

    private

    def request(method, url, **params)
      Rails.logger.error("[wechat] request: #{method} #{url} #{params.inspect}")

      client = Faraday.new(url: BASE_SITE)
      response = client.public_send(method, url, params)
      result = JSON.parse(response.body)

      Rails.logger.error("[wechat] response:#{response.status} #{result.inspect}")

      if response.status != 200
        raise Error, result.inspect
      end

      if result['errcode'].present? && result['errcode'].to_i.nonzero?
        raise Error, result.inspect
      end

      result
    end
  end
end