namespace :db do

namespace :sync do
  desc 'This task updates the local development database with the production data from Heroku'
  task :local, [:heroku_config_database_url] => :environment do |_t, args|
    UI.start 'Syncing the local database from the heroku production one...' do
      UI.heading 'Getting the heroku database url...'
      match_database(args[:heroku_config_database_url])

      UI.heading 'Copying the latest data from the production site...'
      download_remote_data

      UI.heading 'Importing the data in the local database...'
      set_local_data
    end
  end

  desc 'This task updates the staging database with the production data from Heroku'
  task staging: :environment do
    UI.start 'Syncing the staging database with the produciton data from Heroku...' do
      staging_app_name = app_name('staging')
      system "heroku pg:copy #{app_name}::DATABASE_URL DATABASE_URL -a #{staging_app_name} --confirm #{staging_app_name}"
    end
  end

  private

  def match_database(database_url)
    database_url ||= `heroku config:get DATABASE_URL -a #{app_name}`.chomp
    @db = database_url.match(%r{^postgres://(.*?):(.*?)@(.*?):\d*?/(.*?)$})
    fail 'Invalid database url format' unless @db
    UI.message @db
  end

  def download_remote_data
    @export_file = File.join('tmp', 'db-data-dump.sql')
    system "export PGPASSWORD=\"#{@db[2]}\"; pg_dump -U#{@db[1]} -h#{@db[3]} -a -Tschema_migrations #{@db[4]} > #{@export_file}"
    UI.message "DB dump temporarily saved at: #{@export_file}"
  end

  def set_local_data
    Rake::Task['db:drop'].invoke
    Rake::Task['db:create'].invoke
    Rake::Task['db:migrate'].invoke
    database = Rails.configuration.database_configuration[Rails.env]['database']
    system "psql -h localhost #{database} -f #{@export_file}"
    `rm #{@export_file}`
  end

  def app_name(remote_name = 'heroku')
    `git remote -v`.split("\n").map do |remote|
      remote.match(%r{^#{remote_name}\s+(?:https:\/\/)?git[@\.]heroku\.com[:\/](?<app_name>.+)\.git\s+\(push\)})
    end.compact.first[:app_name]
  end
end

end