# frozen_string_literal: true

require 'fileutils'
require 'pathname'
require_relative 'init/configuration'

module JenkinsfileRunner
  module Commands
    class Init
      attr_reader :configuration

      def initialize(argv)
        @configuration = Configuration.new(argv.dup)
      end

      def run
        puts "Running init with #{configuration.inspect}"
        @configuration.validate!

        create_output_directory
        create_jenkinsfile_runner_executable
        copy_jenkins_home_directory
        copy_jenkins_plugins_file
        copy_jenkins_war_file
        create_docker_file
        create_ignore_files
        print_next_steps
      end

      private

      def output_directory
        @output_directory ||= Pathname(configuration.build_output).expand_path
      end

      def create_output_directory
        FileUtils.mkdir_p(output_directory)
      end

      def create_jenkinsfile_runner_executable
        create_file('jenkinsfile-runner') do
          <<~EOF
          java -jar /app/bin/jenkinsfile-runner.jar \
            --jenkins-war "/app/jenkins" \
            --plugins #{jenkins_plugins_path} \
            ${@}
          EOF
        end

        FileUtils.chmod('+x', output_directory.join('jenkinsfile-runner'))
      end

      def copy_jenkins_home_directory
        jenkins_home = Pathname(configuration.jenkins_home).expand_path
        FileUtils.cp_r(jenkins_home, output_directory.join('jenkins_home'))
      end

      def copy_jenkins_war_file
        jenkins_war = Pathname(configuration.jenkins_war).expand_path
        FileUtils.cp(jenkins_war, output_directory)
      end

      def copy_jenkins_plugins_file
        return unless custom_jenkins_plugins

        destination = output_directory.join('jenkins_plugins')
        destination.mkpath if custom_jenkins_plugins.file?

        FileUtils.cp_r(custom_jenkins_plugins, destination)
      end

      def create_docker_file
        create_file('Dockerfile') do
          <<~Dockerfile
          FROM openjdk:11-jdk
          ENV JENKINS_HOME /app/jenkins_home

          #{install_docker_cli}

          RUN mkdir -p /app/bin/ && \\
            wget #{jenkinsfile_runner_binary_url} -O /app/bin/jenkinsfile-runner.jar

          COPY jenkins_home/ /app/jenkins_home
          COPY jenkins.war /app/bin/jenkins.war
          COPY jenkinsfile-runner /app/bin/jenkinsfile-runner

          RUN unzip /app/bin/jenkins.war -d /app/jenkins && \\
              ln -s /app/bin/jenkinsfile-runner /usr/bin/jenkinsfile-runner

          CMD ["/bin/bash"]

          Dockerfile
        end
      end

      def install_docker_cli
        return unless configuration.docker_agent?

        <<~EOF
        RUN apt update && \\
            apt install -y software-properties-common && \\
            curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \\
            add-apt-repository  "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \\
            apt update && \\
            apt install -y docker-ce-cli && \\
            rm -rf /var/lib/apt/lists/*
        EOF
      end

      def create_ignore_files
        content = <<~EOF
        **/*.log
        jenkins_home/jobs
        jenkins_home/logs

        **/*.key
        **/*.key.enc
        jenkins_home/secrets
        jenkins_home/userContent
        jenkins_home/users
        EOF

        create_file('.gitignore') { content }
        create_file('.dockerignore') { content }
      end

      def print_next_steps
        puts <<~EOF
        Please inspect the .dockerignore file to add/remove necessary files for your installation.
        The following files are currently removed:

        #{output_directory.join('.dockerignore').read}
        EOF
      end

      def create_file(name, &block)
        output_directory.join(name).open('w') do |file|
          file.write block.call
        end
      end

      def jenkinsfile_runner_binary_url
        "https://repo.jenkins-ci.org/releases/io/jenkins/jenkinsfile-runner/jenkinsfile-runner/#{jenkinsfile_version}/jenkinsfile-runner-#{jenkinsfile_version}.jar"
      end

      def jenkinsfile_version
        configuration.jfr_version
      end

      def custom_jenkins_plugins
        @custom_jenkins_plugins ||= begin
          return if configuration.jenkins_plugins.to_s.empty?

          Pathname(configuration.jenkins_plugins).expand_path
        end
      end

      def jenkins_plugins_path
        if custom_jenkins_plugins
          Shellwords.escape(custom_output_plugins_path)
        else
          '/app/jenkins_home/plugins/'
        end
      end

      def custom_output_plugins_path
        if custom_jenkins_plugins.file?
          "/app/jenkins_plugins/#{File.basename(custom_jenkins_plugins)}"
        else
          '/app/jenkins_plugins'
        end
      end
    end
  end
end
