# typed: false
# frozen_string_literal: true

require "rails/generators"
require "rails/generators/rails/app/app_generator"

module Hephaestus
  class AppGenerator < Rails::Generators::AppGenerator
    include ExitOnFailure

    hide!

    class_option :version,
      type: :boolean,
      aliases: "-v",
      group: :hephaestus,
      desc: "Show Hephaestus version number and quit"

    class_option :help,
      type: :boolean,
      aliases: "-h",
      group: :hephaestus,
      desc: "Show this help message and quit"

    def finish_template
      say("Invoking Hephaestus customization")
      invoke(:hephaestus_customization)
      super
    end

    def leftovers
      build(:replace_generic_variables)
      generate("hephaestus:license")
      generate("hephaestus:rubocop")

      generate("hephaestus:sorbet")
      invoke(:commit)
      invoke(:outro)
    end

    def hephaestus_customization
      invoke(:customize_gemfile)
      invoke(:copy_github_actions)
      invoke(:setup_development_environment)
      invoke(:setup_staging_environment)
      invoke(:setup_production_environment)
      invoke(:setup_test_environment)
      invoke(:configure_app)
      invoke(:purge_unneeded_files)
      invoke(:copy_vscode_settings)
      invoke(:generate_default)
      invoke(:create_github_repo)
    end

    def customize_gemfile
      build(:replace_gemfile)
      bundle_command("install")
      bundle_command("lock --add-platform x86_64-linux")
    end

    def copy_github_actions
      source = File.join(Hephaestus::AppGenerator.source_root, ".github")
      directory(source, ".github")
    end

    def setup_development_environment
      say("Setting up the development environment")
      build(:configure_local_mail)
      build(:raise_on_delivery_errors)
      build(:configure_dev_hosting)
      build(:copy_setup_scripts)
    end

    def copy_vscode_settings
      source = File.join(Hephaestus::AppGenerator.source_root, ".vscode")
      directory(source, ".vscode")
    end

    def purge_unneeded_files
      remove_dir("app/assets")
      remove_file("app/controllers/concerns/.keep")
      remove_dir("app/helpers")
      remove_dir("app/models")
      remove_dir("app/views/layouts")
      remove_dir("lib/assets")
      remove_dir("lib/tasks/.keep")
      remove_dir("test/helpers")
      remove_dir("test/channels")
      remove_dir("test/models")
    end

    def setup_staging_environment
      build(:setup_staging_environment)
    end

    def setup_production_environment
      say("Setting up the production environment")
      build(:setup_asset_host)
      build(:setup_background_worker)
      build(:setup_slack_logger)
    end

    def setup_test_environment
      say("Setting up the test environment")
      build(:setup_test_environment)
    end

    def configure_app
      say("Configuring app")
      build(:configure_time_formats)
    end

    def create_github_repo
      if !options[:skip_git] && options[:github]
        say("Creating Github repo")
        build(:create_github_repo, options[:github])
      end
    end

    def generate_default
      run("spring stop > /dev/null 2>&1 || true")

      generate("hephaestus:core")
      generate("hephaestus:deployment")
      generate("hephaestus:lib")

      # keep this at the end
      generate("hephaestus:config")
    end

    def commit
      run("git add .")
      run("git commit -m 'Initial commit'")
    end

    def outro
      say("\nCongratulations! You just made a plug.")
      say("\nTry running `rails c` to ensure that everything was set up correctly.")
      say("\nRunning `rake test` is also a good idea.")
    end

    class << self
      def banner
        "hephaestus #{arguments.map(&:usage).join(" ")} [options]"
      end
    end

    protected

    def get_builder_class # rubocop:disable Naming/AccessorMethodName
      Hephaestus::AppBuilder
    end

    def using_active_record?
      !options[:skip_active_record]
    end
  end
end