# frozen_string_literal: true namespace :db do

desc "Identify differences from your schema"
task :dif_schema, [:remote_connection_string] => [:environment] do |task, args|
  require 'pg'

  sql = <<-SQL
    select
      table_name,
      column_name,
      is_nullable,
      data_type,
      character_maximum_length,
      numeric_precision
    from
      information_schema.columns
    where
      table_schema = 'salesforce' and
      table_name != '_trigger_log_archive' and
      table_name != '_trigger_log' and
      table_name != '_sf_event_log' and
      table_name != '_hcmeta'
    order by
      table_name,
      ordinal_position
    ;
  SQL

  remote_conn = args[:remote_connection_string] || ENV["HC_URL"] || ENV["HEROKUCONNECT_URL"] || fail(<<-MSG)
    Must specify remote_connection_string or provide ENV[HC_URL].
    Try
      export HC_URL="$(heroku config:get DATABASE_URL)"

  MSG
  remote = PG::Connection.new(remote_conn).async_exec(sql).each.to_a
  local = ApplicationRecord.connection.raw_connection.async_exec(sql).each.to_a

  remote.each {|c| c["character_maximum_length"] = c["character_maximum_length"].to_i }
  local.each {|c| c["character_maximum_length"] = c["character_maximum_length"].to_i }

  def format_column(c)
    nul = (c["is_nullable"] == "YES")
    length = c["character_maximum_length"] ? ", limit: #{c["character_maximum_length"]}" : ""
    precision = c["numeric_precision"] ? ", precision: #{c["numeric_precision"]}" : ""
    type = c["data_type"].inspect
    type = ':string' if c["data_type"] == "character varying"
    "_column :#{c["table_name"]}, :#{c["column_name"]}, #{type}, null: #{nul.to_s} #{length} #{precision}"
  end

  local = local.map &method(:format_column)
  remote = remote.map &method(:format_column)

  if (local - remote).any?
    puts "***************************************************"
    puts "**      Extra columns locally not in remote      **"
    puts "***************************************************"
    (local - remote).each do |c|
      puts "remove" + c
    end

  end

  if (remote - local).any?
    puts "***************************************************"
    puts "** Extra columns on remote not available locally **"
    puts "***************************************************"
    (remote - local).each do |c|
      puts "add" + c
    end
  end

  abort "Differences found" if (local - remote).any? or (remote - local).any?
end

end