# typed: false
# frozen_string_literal: true

require "forwardable"

module Hephaestus
  class AppBuilder < ::Rails::AppBuilder
    include Hephaestus::Actions
    extend Forwardable

    def readme
      template("README.md.erb", "README.md")
    end

    def gitignore
      copy_file("hephaestus_gitignore", ".gitignore")
    end

    def gemfile
      template("Gemfile.erb", "Gemfile")
    end

    def raise_on_delivery_errors
      replace_in_file(
        "config/environments/development.rb",
        "raise_delivery_errors = false",
        "raise_delivery_errors = true",
      )
    end

    def copy_setup_scripts
      source = File.join(Hephaestus::AppGenerator.source_root, "script")
      directory(source, "script")
      Dir.glob("script/**/*").each do |file|
        next if File.directory?(file)

        chmod(file, 0o755)
      end
    end

    def configure_dev_hosting
      config = <<~EOD
        # Let dev server run on GitHub Codespaces
        config.hosts << /[a-z0-9-]+.githubpreview.dev/

        # Let dev server run on ngrok domains
        config.hosts << /[a-z0-9-]+.ngrok.io/
      EOD

      configure_environment("development", config)
    end

    def setup_asset_host
      config = <<~EOD
        config.public_file_server.headers = {
            "Cache-Control" => "public, max-age=31557600",
          }
      EOD

      configure_environment("production", config)
    end

    def setup_background_worker
      config = <<~EOD
        # Use a real queuing backend for Active Job (and separate queues per environment).
        config.active_job.queue_adapter = :sidekiq
      EOD
      configure_environment("production", config)
      configure_environment("staging", config)
    end

    def setup_slack_logger
      config = <<~EOD
        config.after_initialize do
          Rails.logger.extend(ActiveSupport::Logger.broadcast(SlackWebhookLogger.logger))
        end
      EOD
      configure_environment("production", config)
      configure_environment("staging", config)
      configure_environment("test", config)
    end

    def setup_staging_environment
      FileUtils.cp(File.join(destination_root, "config/environments/production.rb"), File.join(destination_root, "config/environments/staging.rb"))
    end

    def replace_gemfile
      template("Gemfile.erb", "Gemfile", force: true) do |content|
        if development_env?
          content.gsub(/gem .hephaestus./) { |s| %(#{s}, path: "#{root_path}") }
        else
          content
        end
      end
    end

    def ruby_version
      create_file(".ruby-version", "#{Hephaestus::RUBY_VERSION}\n")
    end

    def configure_time_formats
      replace_in_file("config/application.rb", /# config.time_zone = .*/, "config.time_zone = \"UTC\"")
    end

    def create_github_repo(repo_name)
      run("gh repo create #{repo_name}")
    end

    def remove_config_comment_lines
      config_files = [
        "application.rb",
        "environment.rb",
        "environments/development.rb",
        "environments/production.rb",
        "environments/test.rb",
      ]

      config_files.each do |config_file|
        path = Pathname(destination_root).join("config", config_file)
        source = Actions::StripCommentsAction.call(path.read)

        path.write(source)
      end
    end

    def remove_routes_comment_lines
      replace_in_file(
        "config/routes.rb",
        /Rails\.application\.routes\.draw do.*end/m,
        "Rails.application.routes.draw do\nend",
      )
    end

    def setup_test_environment
      remove_dir("test")
      source = File.join(Hephaestus::AppGenerator.source_root, "test")
      directory(source, "test")
    end

    def replace_generic_variables
      replace_in_files(destination_root, "${APP}", app_name.titlecase)
      replace_in_files(destination_root, "PlugApp", app_name.underscore.camelcase)
      replace_in_files(destination_root, "plug-app", app_name.dasherize)
      replace_in_files(destination_root, "PLUG_APP", app_name.underscore.upcase)
      replace_in_files(destination_root, "plug_app", app_name.underscore)
    end

    private

    def root_path
      @root_path ||= Pathname(__dir__).join("..", "..").expand_path
    end

    def development_env?
      root_path.join("hephaestus.gemspec").exist?
    end

    def raise_on_missing_translations_in(environment)
      config = "config.i18n.raise_on_missing_translations = true"

      uncomment_lines("config/environments/#{environment}.rb", config)
    end

    def heroku_adapter
      @heroku_adapter ||= Adapters::Heroku.new(self)
    end
  end
end