# frozen_string_literal: true require 'json' require 'bundler' require 'hashdiff' Bundler.require namespace :salesforce do

namespace :schema do
  desc "Save the salesforce schema for the given app"
  task :dump, [:app_name] do |_t, args|
    env = ENV
    outfile = 'salesforce-schema.json'

    if args[:app_name] && args[:app_name].length > 0
      require 'dotenv'
      heroku_out = `heroku config --app #{args[:app_name]} --shell`
      raise "Error fetching heroku config for #{args[:app_name]}: #{heroku_out}" unless $?.success?
      env = Dotenv::Parser.call(heroku_out)
      outfile = "salesforce-schema-#{args[:app_name]}.json"
    end
    outfile = ENV.fetch("SCHEMA_FILE", outfile)

    require 'connect/api_adapter'
    description = Connect::ApiAdapter.describe(env).group_by {|e| e["name"] }
    description.each do |k, v|
      raise "Expected name to be unique" unless v.one?
      description[k] = v.first
      description[k].delete("name")
    end

    q = <<-SQL
      Select
        Id,
        ValidationName,
        Description,
        EntityDefinition.DeveloperName,
        ErrorDisplayField,
        ErrorMessage
      From
        ValidationRule
      where
        Active = true
      order by
        Id
    SQL
    validations = Connect::ApiAdapter.tooling(env).query(q)
    formatted_validations = {}
    validations.each {|v| formatted_validations[v.dig('Id')] = {
      description: v['Description'],
      column: v.dig("EntityDefinition", 'DeveloperName'),
      show_on: v['ErrorDisplayField'],
      message: v['ErrorMessage'],
      name: v['ValidationName'],
    }}

    File.write(
      outfile,
      JSON.pretty_generate({schema: description, validations: formatted_validations})
    )
  end

# Select Id,Active,Description,ErrorDisplayField, ErrorMessage From ValidationRule Where EntityDefinition.QualifiedApiName = 'SVMXC__Parts_Request__c'

  desc "Diff two schema files against one another"
  task :diff, [:old, :new] do |_t, args|
    old_h = JSON.parse(File.read(args[:old]))
    new_h = JSON.parse(File.read(args[:new]))

    removed = old_h.keys - new_h.keys
    added = new_h.keys - old_h.keys
    diff = false
    removed.each do |r|
      puts "Removed object: #{r}"
      diff = true
    end
    added.each do |a|
      puts "Added object: #{a}"
      diff = true
    end

    removed.each {|k| old_h.delete(k)}
    added.each {|k| new_h.delete(k)}

    HashDiff.diff(old_h, new_h).each do |sym, key, old, new_val|
      diff = true
      case sym
      when "~"
        puts "Changed #{key} from #{old} to #{new_val}"
      when "-"
        puts "Removed #{key}"
      when "+"
        puts "Added #{key} = #{old}"
      else
        raise "Unknown HashDiff symbol '#{sym}', expected one of '~', '+' or '-'."
      end
    end

    exit(1) if diff
  end
end

end