class ViteRuby::CLI::Install

def call(**)

def call(**)
  $stdout.sync = true
  say 'Creating binstub'
  ViteRuby.commands.install_binstubs
  say 'Creating configuration files'
  create_configuration_files
  say 'Installing sample files'
  install_sample_files
  say 'Installing js dependencies'
  install_js_dependencies
  say 'Adding files to .gitignore'
  install_gitignore
  say "\nVite ⚡️ Ruby successfully installed! 🎉"
end

def copy_template(path, to:)

def copy_template(path, to:)
  cp TEMPLATES_PATH.join(path), to
end

def create_configuration_files

Internal: Creates the Vite and vite-plugin-ruby configuration files.
def create_configuration_files
  copy_template 'config/vite.config.ts', to: root.join('vite.config.ts')
  setup_app_files
  ViteRuby.reload_with('VITE_RUBY_CONFIG_PATH' => config.config_path)
end

def install_gitignore

Internal: Adds compilation output dirs to git ignore.
def install_gitignore
  return unless (gitignore_file = root.join('.gitignore')).exist?
  append(gitignore_file, <<~GITIGNORE)
    # Vite Ruby
    /public/vite
    /public/vite-dev
    /public/vite-test
    node_modules
    *.local
    .DS_Store
  GITIGNORE
end

def install_js_dependencies

Internal: Installs vite and vite-plugin-ruby at the project level.
def install_js_dependencies
  package_json = root.join('package.json')
  write(package_json, '{}') unless package_json.exist?
  Dir.chdir(root) do
    deps = "vite@#{ ViteRuby::DEFAULT_VITE_VERSION } vite-plugin-ruby@#{ ViteRuby::DEFAULT_PLUGIN_VERSION }"
    _, stderr, status = ViteRuby::IO.capture("npx --package @antfu/ni -- ni -D #{ deps }", stdin_data: "\n")
    _, stderr, = ViteRuby::IO.capture("yarn add -D #{ deps }") unless status.success?
    say("Could not install JS dependencies.\n", stderr) unless stderr.to_s.empty?
  end
end

def install_sample_files

Internal: Create a sample JS file and attempt to inject it in an HTML template.
def install_sample_files
  copy_template 'entrypoints/application.js', to: config.resolved_entrypoints_dir.join('application.js')
end

def root

Internal: The root path for the Ruby application.
def root
  @root ||= silent_warnings { config.root }
end

def say(*args)

def say(*args)
  $stdout.puts(*args)
end

def setup_app_files

Internal: Setup for a plain Rack application.
def setup_app_files
  copy_template 'config/vite.json', to: config.config_path
  if (rackup_file = root.join('config.ru')).exist?
    inject_line_after_last rackup_file, 'require', 'use(ViteRuby::DevServerProxy, ssl_verify_none: true) if ViteRuby.run_proxy?'
  end
end

def silent_warnings

Internal: Avoid printing warning about missing vite.json, we will create one.
def silent_warnings
  old_stderr = $stderr
  $stderr = StringIO.new
  yield
ensure
  $stderr = old_stderr
end