require "aws-sdk"
require "dotenv"
require_relative "../support/run_log"
require_relative "../support/env_files"
require_relative "../support/helpers/accounting_run"
require_relative "cuke/task_runner"
require "byebug"
require "rainbow/ext/string" # for colored output

module Rake
  class Task
    alias_method :old_execute, :execute
    def execute(args = nil)
      puts "[rake] starting #{@name}"
      old_execute(args)
      puts "[rake] finished #{@name}"
    end
  end # class Task
end # module Rake

namespace :cucumber do
  ## Example task
  # task :example do
  #   Cuke::TaskRunner.new(
  #     files: ["features/"], # so we can do legacy vs. standalone
  #     parallel: true, # if we want to parallelize
  #     parallel_opts: { count: 2 }, # use 2 threads
  #     with_rerun: true, # if we want to rerun failures outputted to rerun.txt
  #     cucumber_opts: %w(--pretty), # add any additional cucumber opts you want here
  #     minimal_run: true # instantiate Cuke::Run::Minimal instead of default (presently Cuke::Run::Parallel)
  #     profile: nil # select profile from cucumber.yml
  #     # By default, Cuke::TaskRunner checks whether a profile exists with a
  #     #   name matching the task name, i.e. if `cucumber -p example` is a
  #     #   valid profile it will automatically add it to cucumber_opts.
  #     # Therefore:
  #     # DON'T add a profile to cucumber_opts.
  #     # DON'T add formatters here, they already exist in Cuke::Run::Parallel, ::Serial and ::Rerun, etc.
  #     # DON'T create a task that simply wraps a Rake task. See
  #     #   Cuke::Run::Parallel#run for the correct way to do this.
  #     # DO ensure cucumber_opts is an Array. The logic to transform it to a String for use by, e.g.
  #     #   the parallel_tests gem, lives in Cuke::Run::Parallel#run.
  #     # If you need to create a custom Cuke::Run::CustomBuild class with
  #     #   special dynamic/runtime processing just subclass the appropriate
  #     #   Run class. See Cuke::Run::PRBuilder for example.
  #     # To view defaults, see Cuke::TaskRunner's constructor
  #   )
  # end

  desc "Run all scenarios in the legacy suite"
  task full_legacy_run: [:legacy]

  task :unused do
    # Note that this will break on steps missing step definitions
    Cuke::TaskRunner.new(
      parallel: false,
      with_rerun: false,
      minimal_run: true,
      profile: "unused"
      # runs against all features
    )
  end

  task :dry_run do
    Cuke::TaskRunner.new(
      parallel: false,
      with_rerun: false,
      minimal_run: true,
      profile: "dry_run"
      # runs against all features
    )
  end

  task :cache_warm do
    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      with_rerun: false,
      profile: "require_features",
      cucumber_opts: [
        "CUCUMBER_PROFILE=cache_warm",
        "--tags 'not @wip'",
        "--tags @cache_warm"
      ]
    )
  end

  desc "Run all legacy scenarios in parallel on the grid"
  task :legacy do
    ENV["PRESERVE_WORKSPACE"] = "true"
    require_relative "../support/require_order"

    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      profile: "require_features",
      parallel: true,
      parallel_opts: {
        count: 24
      },
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "--tags '@legacy and not @wip'"
      ]
    )
  end

  desc "Run subset of legacy scenarios in parallel on the grid"
  task :regression_legacy do
    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      profile: "require_features",
      parallel: true,
      parallel_opts: {
        count: 24
      },
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "--tags @regression",
        "--tags 'not @wip'"
      ]
    )
  end

  desc "Run OA subset of legacy scenarios in parallel on the grid"
  task :legacy_oa do
    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      profile: "require_features",
      parallel: true,
      parallel_opts: {
        count: 24
      },
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "--tags '@oa+workstation or @oa and @legacy'",
        "--tags 'not @wip'"
      ]
    )
  end

  desc "Run Workstation subset of legacy scenarios in parallel on the grid"
  task :legacy_workstation do
    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      profile: "require_features",
      parallel: true,
      parallel_opts: {
        count: 24
      },
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "--tags '@legacy and not @oa'",
        "--tags 'not @wip'"
      ]
    )
  end

  desc "Run all standalone scenarios on the grid"
  task :standalone do
    Cuke::TaskRunner.new(
      files: ["features/standalone"],
      parallel: true,
      parallel_opts: {
        count: 15
      },
      # might fail due to unsynchronized deployments, so rerun would be best.
      with_rerun: true,
      profile: "require_features",
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "DOMAIN_PROFILE=standalone",
        "--tags 'not @wip'",
        "--tags 'not @frontend_royalties'",
        # dpb2 will cause dpb1 scenarios in parallel to fail
        "--tags 'not @dpb2'"
      ]
    )
  end

  desc("Monthly accounting run sanity check")
  task :accounting_run_monthly do
    ENV["PRESERVE_WORKSPACE"] = "true"
    require_relative "../support/require_order"

    if Support::Helpers::AccountingRun.in_progress?
      puts "Accounting run in progress! Can't run accounting run scenarios."
    else
      Cuke::TaskRunner.new(
        files: ["features/accounting_run"],
        profile: "require_features",
        parallel: false,
        with_rerun: true,
        cucumber_opts: [
          "CUCUMBER_PROFILE=grid",
          "--tags @accounting_run_monthly",
          "--tags 'not @wip'"
        ]
      )
    end
  end

  desc(
    "Quarterly accounting run sanity check.
     Runs both @accounting_run_monthly and @accounting_run_quarterly"
  )
  task :accounting_run_quarterly do
    ENV["PRESERVE_WORKSPACE"] = "true"
    require_relative "../support/require_order"

    if Support::Helpers::AccountingRun.in_progress?
      puts "Accounting run in progress! Can't run accounting run scenarios."
    else
      Cuke::TaskRunner.new(
        files: ["features/accounting_run"],
        profile: "require_features",
        parallel: false,
        with_rerun: true,
        cucumber_opts: [
          "CUCUMBER_PROFILE=grid",
          "--tags @accounting_run_sanity_check",
          "--tags 'not @wip'"
        ]
      )
    end
  end

  task :mobile_analytics do
    Cuke::TaskRunner.new(
      files: ["features/standalone"],
      # total of two scenarios. no need for a parallel build.
      parallel: false,
      # might fail due to unsynchronized deployments, so rerun would be best.
      with_rerun: true,
      profile: "require_features",
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "DOMAIN_PROFILE=standalone",
        "--tags 'not @wip'",
        "--tags @mobile_analytics"
      ]
    )
  end

  # runs @fast. useful for debugging build processes
  task :fast_ci do
    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      profile: "require_features",
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "--tags @fast"
      ]
    )
  end

  task :prod do
    Cuke::TaskRunner.new(
      files: ["features/production"],
      parallel: false,
      # ideally, reruns wouldn't happen, but image upload has some problems
      with_rerun: true,
      profile: "require_features",
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "DOMAIN_PROFILE=production",
        "--tags 'not @wip'"
      ]
    )
  end

  desc "Create .env file from .env.shadow"
  task :init_dotenv do
    from_file_name = ".env.shadow"
    to_file_name = ".env"
    FileUtils.cp(from_file_name, to_file_name)
    puts "[rake] #{from_file_name} copied to #{to_file_name} successfully!".color(:green)
  end

  desc "Upload all logs to the cukes-logs S3 bucket"
  task :store_all_logs do
    Support::RunLog.send_all_logs
  end

  desc "Download .env file from S3"
  task :sync_env do
    Support::EnvFiles.load_env_file
    Support::EnvFiles.download_env_from_s3
  end

  desc "Upload .env file to S3."
  task :update_env do
    Support::EnvFiles.load_env_file
    Support::EnvFiles.upload_env_to_s3
  end

  desc "Run linters and unit tests against the current branch"
  task pr: ["lint", "spec:test_the_tests", "cucumber:dry_run"]

  desc "Run regression tests for workstation account permissions"
  task :alw_grass_roles do
    Cuke::TaskRunner.new(
      files: ["features/alw_grass_roles_perms"],
      parallel: false,
      with_rerun: true,
      profile: "require_features",
      cucumber_opts: [
        "CUCUMBER_PROFILE=grid",
        "--tags 'not @wip'",
        "--tags @alw_grass_roles"
      ]
    )
  end

  desc "Run smoke tests against squad box."
  task :dev do
    Cuke::TaskRunner.new(
      files: ["features/legacy"],
      profile: "require_features",
      parallel: false,
      cucumber_opts: [
        "CUCUMBER_PROFILE=developer",
        "DOMAIN_PROFILE=developer",
        "--tags 'not @wip'",
        "--tags '@smoke_dev'"
      ]
    )
  end
end
