#!/usr/bin/env ruby
#
# frozen_string_literal: true

require 'socket'
require_relative '../../lib/gdk'

class SetupWorkspace
  ROOT_DIR = '/projects/gitlab-development-kit'
  GDK_SETUP_FLAG_FILE = "#{ROOT_DIR}/.cache/.gdk_setup_complete".freeze

  def initialize
    @hostname = Socket.gethostname
    @ip_address = Socket.ip_address_list.find(&:ipv4_private?)&.ip_address
    port = ENV.find { |key, _| key.include?('SERVICE_PORT_GDK') }&.last
    @url = ENV.fetch('GL_WORKSPACE_DOMAIN_TEMPLATE', '').gsub('${PORT}', port.to_s)
  end

  def run
    return GDK::Output.info(%(Nothing to do as we're not a GitLab Workspace.\n\n)) unless gitlab_workspace_context?

    if bootstrap_needed?
      success, duration = execute_bootstrap
      create_flag_file if success
      configure_telemetry

      send_telemetry(success, duration) if allow_sending_telemetry?
    else
      GDK::Output.info("#{GDK_SETUP_FLAG_FILE} exists, GDK has already been bootstrapped.\n\nRemove the #{GDK_SETUP_FLAG_FILE} to re-bootstrap.")
    end
  end

  private

  def gitlab_workspace_context?
    ENV.key?('GL_WORKSPACE_DOMAIN_TEMPLATE') && Dir.exist?(ROOT_DIR)
  end

  def bootstrap_needed?
    !File.exist?(GDK_SETUP_FLAG_FILE)
  end

  def execute_bootstrap
    start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    configure_gdk

    # Instead GDK::Shellout use Process.spawn to let the process reuse the interactive TTY.
    # This is cructial to run command like `gdk update` in parallel.
    pid = Process.spawn('support/gitlab-remote-development/remote-development-gdk-bootstrap.sh', chdir: ROOT_DIR)
    success = Process::Status.wait(pid).success?

    duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start

    [success, duration]
  end

  def allow_sending_telemetry?
    GDK.config.telemetry.enabled
  end

  def configure_gdk
    new_values = {
      'listen_address' => @ip_address.to_s,
      'gitlab.rails.hostname' => @url.to_s,
      'gitlab.rails.https.enabled' => true,
      'gitlab.rails.port' => 443,
      'gitlab_shell.skip_setup' => true,
      'gitaly.skip_setup' => true,
      'vite.enabled' => true,
      'vite.hot_module_reloading' => false,
      'webpack.enabled' => false,
      'telemetry.environment' => 'remote-development'
    }

    GDK.config.bury_multiple!(new_values)
    GDK.config.save_yaml!
  end

  def configure_telemetry
    answer = 'y' if GDK::Telemetry.team_member?
    answer ||= GDK::Output.prompt(GDK::Telemetry::PROMPT_TEXT)
    GDK::Telemetry.update_settings(answer)
  end

  def send_telemetry(success, duration)
    GDK::Telemetry.send_telemetry(success, 'setup-workspace', duration: duration)
    GDK::Telemetry.flush_events
  end

  def create_flag_file
    FileUtils.mkdir_p(File.dirname(GDK_SETUP_FLAG_FILE))
    FileUtils.touch(GDK_SETUP_FLAG_FILE)
    GDK::Output.success("You can access your GDK here: https://#{@url}")
  end
end

SetupWorkspace.new.run if $PROGRAM_NAME == __FILE__
