# frozen_string_literal: true

module Gitlab
  module QA
    module Component
      class Praefect < Base
        extend Forwardable
        using Rainbow
        attr_reader :release
        attr_accessor :cluster_config
        attr_writer :name

        def_delegators :release, :tag, :image, :edition

        def initialize
          super
          self.release = 'CE'
          @cluster_config = Component::GitalyCluster::GitalyClusterConfig.new
          @ports = [cluster_config.praefect_port]
        end

        def name
          @name || "praefect-#{SecureRandom.hex(4)}"
        end

        def release=(release)
          @release = QA::Release.new(release)
        end

        def pull
          docker.login(**release.login_params) if release.login_params

          super
        end

        def reconfigure
          setup_omnibus
          @docker.attach(name) do |line|
            # TODO, workaround which allows to detach from the container
            break if /gitlab Reconfigured!/.match?(line)
          end
        end

        def setup_omnibus
          @docker.write_files(name) do |f|
            f.write('/etc/gitlab/gitlab.rb', praefect_omnibus_configuration)
          end
        end

        def wait_until_ready
          @docker.exec(name, 'praefect -config /var/opt/gitlab/praefect/cluster_config.toml check || true') do |resp|
            Runtime::Logger.info(resp)
            break if /All checks passed/.match?(line)
          end
        end

        def praefect_omnibus_configuration # rubocop:disable Metrics/AbcSize
          <<~OMNIBUS
              #{GitalyCluster.disable_other_omnibus_services}
              gitaly['enable'] = false;
              prometheus['enable'] = true;
              praefect['enable'] = true;
              praefect['listen_addr'] = '0.0.0.0:#{cluster_config.praefect_port}';
              praefect['prometheus_listen_addr'] = '0.0.0.0:9652';
              praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN';
              praefect['reconciliation_scheduling_interval'] = '10s';
              praefect['database_host'] = '#{cluster_config.database_node_addr}';
              praefect['database_user'] = 'postgres';
              praefect['database_port'] = #{cluster_config.database_port};
              praefect['database_password'] = 'SQL_PASSWORD';
              praefect['database_dbname'] = 'praefect_production';
              praefect['database_sslmode'] = 'disable';
              praefect['database_direct_host'] = '#{cluster_config.database_node_addr}';
              praefect['database_direct_port'] = #{cluster_config.database_port};
              praefect['virtual_storages'] = {
                'default' => {
                  'nodes' => {
                    '#{cluster_config.primary_node_name}' => {
                      'address' => 'tcp://#{cluster_config.primary_node_addr}:#{cluster_config.primary_node_port}',
                      'token'   => 'PRAEFECT_INTERNAL_TOKEN'
                    },
                    '#{cluster_config.secondary_node_name}' => {
                      'address' => 'tcp://#{cluster_config.secondary_node_addr}:#{cluster_config.secondary_node_port}',
                      'token'   => 'PRAEFECT_INTERNAL_TOKEN'
                    },
                    '#{cluster_config.tertiary_node_name}' => {
                      'address' => 'tcp://#{cluster_config.tertiary_node_addr}:#{cluster_config.tertiary_node_port}',
                      'token'   => 'PRAEFECT_INTERNAL_TOKEN'
                    }
                  }
                }
              };
          OMNIBUS
        end
      end
    end
  end
end