# frozen_string_literal: true
class CustomWizard::Api::Endpoint
  include ActiveModel::SerializerSupport

  attr_accessor :id, :name, :api_name, :method, :url, :content_type, :success_codes

  def initialize(api_name, data = {})
    @api_name = api_name

    data.each { |k, v| self.send "#{k}=", v if self.respond_to?(k) }
  end

  def self.set(api_name, new_data)
    if new_data["id"]
      data = self.get(api_name, new_data["id"], data_only: true)
      endpoint_id = new_data["id"]
    else
      data = {}
      endpoint_id = SecureRandom.hex(3)
    end

    new_data.each { |k, v| data[k.to_sym] = v }

    PluginStore.set("custom_wizard_api_#{api_name}", "endpoint_#{endpoint_id}", data)

    self.get(api_name, endpoint_id)
  end

  def self.get(api_name, endpoint_id, opts = {})
    return nil if !endpoint_id

    if data = PluginStore.get("custom_wizard_api_#{api_name}", "endpoint_#{endpoint_id}")
      if opts[:data_only]
        data
      else
        data[:id] = endpoint_id
        self.new(api_name, data)
      end
    else
      nil
    end
  end

  def self.remove(api_name)
    PluginStoreRow.where(
      "plugin_name = 'custom_wizard_api_#{api_name}' AND key LIKE 'endpoint_%'",
    ).destroy_all
  end

  def self.list(api_name)
    PluginStoreRow
      .where("plugin_name LIKE 'custom_wizard_api_#{api_name}' AND key LIKE 'endpoint_%'")
      .map do |record|
        api_name = record["plugin_name"].sub("custom_wizard_api_", "")
        data = ::JSON.parse(record["value"])
        data[:id] = record["key"].split("_").last
        self.new(api_name, data)
      end
  end

  def self.request(user = Discourse.system_user, api_name, endpoint_id, body)
    endpoint = self.get(api_name, endpoint_id)
    auth_string = CustomWizard::Api::Authorization.authorization_string(api_name)
    content_type = endpoint.content_type

    headers = {}
    headers["Authorization"] = auth_string if auth_string
    headers["Content-Type"] = content_type if content_type

    connection = Excon.new(endpoint.url, headers: headers)

    params = { method: endpoint.method }

    if body
      if content_type === "application/json"
        body = JSON.generate(body)
      elsif content_type === "application/x-www-form-urlencoded"
        body = URI.encode_www_form(body)
      end

      params[:body] = body
    end

    response = connection.request(params)

    if endpoint.success_codes.include?(response.status)
      begin
        result = JSON.parse(response.body)
      rescue JSON::ParserError
        result = response.body
      end

      CustomWizard::Api::LogEntry.set(api_name, log_params(user, "SUCCESS", endpoint.url))

      result
    else
      message = "API request failed"
      CustomWizard::Api::LogEntry.set(api_name, log_params(user, "FAIL", endpoint.url, message))
      { error: message }
    end
  end

  def self.log_params(user, status, url, message = "")
    { time: Time.now, user_id: user.id, status: status, url: url, error: message }
  end
end
