module Webhook::Client  

  # uuid SecureRandom.uuid
  #  hmac = OpenSSL::HMAC.new(secret, OpenSSL::Digest::SHA1.new)
  #  message = Gitea::WebhookTask.last.read_attribute_before_type_cast("payload_content")
  # hmac.update(message)
  # sha1 = hmac.digest.unpack('H*').first

  attr_reader :uuid, :event, :http_method, :content_type, :url, :secret, :payload_content, :webhook
  attr_accessor :request_content, :response_content, :webhook_task

  def initialize(opts)
    @uuid = opts[:uuid]
    @event = opts[:event]
    @webhook = opts[:webhook]
    @http_method = @webhook.http_method
    @content_type = @webhook.content_type
    @url = @webhook.url
    @secret = @webhook.secret
    @payload_content = opts[:payload_content]
    @request_content = {}
    @response_content = {}
    @webhook_task = Gitea::WebhookTask.create(
      hook_id: @webhook.id,
      uuid: @uuid,
      payload_content: @payload_content,
      event_type: @event,
      is_delivered: true
    )
  end

  def do_request 
    headers = {}
    headers['Content-Type'] = trans_content_type
    headers["X-Gitea-Delivery"] = @uuid 
    headers["X-Gitea-Event"] = @event 
    headers["X-Gitea-Event-Type"] = @event
    headers["X-Gitea-Signature"] = signatureSHA256
    headers["X-Gogs-Delivery"] = @uuid 
    headers["X-Gogs-Event"] = @event 
    headers["X-Gogs-Event-Type"] = @event 
    headers["X-Gogs-Signature"] = signatureSHA256
    headers["X-Hub-Signature"] = "sha1=" + signatureSHA1
    headers["X-Hub-Signature-256"] = "sha256=" + signatureSHA256
    headers["X-GitHub-Delivery"] = @uuid 
    headers["X-GitHub-Event"] = @event 
    headers["X-GitHub-Event-Type"] = @event
    @request_content["url"] = @url 
    @request_content["http_method"] = @http_method
    @request_content["headers"] = headers

    begin 

      response = RestClient::Request.execute(method: trans_http_method, url: @url, headers: headers, payload: @webhook_task.read_attribute_before_type_cast("payload_content")) {|response, request, result| response }

      @response_content["status"] = response.code 
      @response_content["headers"] = response.headers 
      @response_content["body"] = response.body

    rescue => e
      @response_content["status"] = 500 
      @response_content["headers"] = {}
      @response_content["body"]  = e.message
    end

    @webhook_task.update_attributes({
      delivered: Time.now.to_i * 1000000000,
      is_succeed: @response_content["status"] < 300,
      request_content: @request_content,
      response_content: @response_content
    })


    return @request_content, @response_content, @webhook_task
  end

  def request_content 
    @request_content
  end

  def response_content 
    @response_content 
  end

  def webhook_task 
    @webhook_task
  end

  private 
  def signatureSHA1
    hmac = OpenSSL::HMAC.new(@secret, OpenSSL::Digest::SHA1.new)
    message = @payload_content

    hmac.digest.unpack('H*').first
  end

  def signatureSHA256
    hmac = OpenSSL::HMAC.new(@secret, OpenSSL::Digest::SHA256.new)
    message = @payload_content

    hmac.digest.unpack('H*').first
  end

  def trans_content_type 
    if @content_type == "form"
      return "application/x-www-form-urlencoded"
    else 
      return "application/json"
    end
  end

  def trans_http_method 
    if @http_method == "GET"
      return :get
    else 
      return :post
    end
  end

end