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

require 'json'
require_relative 'file_locations'
require_relative 'file_verifier'
require_relative 'runtime_verifier'
require_relative 'expectations'
require_relative 'operations/enable'
require_relative 'operations/disable'
require_relative 'operations/register'
require_relative 'operations/unregister'
require_relative 'operations/audit'
require_relative 'operations/list'
require_relative 'operations/validate'

module PluginConfig
  OPERATIONS = {
    'enable' => Operations::Enable,
    'disable' => Operations::Disable,
    'register' => Operations::Register,
    'unregister' => Operations::Unregister,
    'audit' => Operations::Audit,
    'list' => Operations::List,
    'validate' => Operations::Validate
  }.freeze

  def self.run(argv)
    operation_name = argv.shift

    unless operation_name && OPERATIONS.key?(operation_name)
      valid = OPERATIONS.keys.join(', ')
      $stderr.puts JSON.pretty_generate(
        error: 'invalid_operation',
        message: "Usage: plugin_config.rb <operation> [--key=value ...]",
        valid_operations: valid
      )
      exit 1
    end

    params = {}
    snapshot_requested = false

    argv.each do |arg|
      if arg == '--snapshot'
        snapshot_requested = true
      elsif arg.start_with?('--')
        key, value = arg.sub(/^--/, '').split('=', 2)
        params[key.to_sym] = value
      end
    end

    runtime = RuntimeVerifier.new if snapshot_requested
    before = runtime&.snapshot

    operation = OPERATIONS[operation_name].new(params)
    result = operation.call

    if snapshot_requested && runtime
      after = runtime.snapshot
      result[:runtime_diff] = RuntimeVerifier.diff(before, after)
    end

    puts JSON.pretty_generate(result)
    exit(result[:valid] == false ? 1 : 0)
  rescue SchemaError => e
    $stderr.puts JSON.pretty_generate(e.to_diagnostic_json)
    exit 2
  rescue StandardError => e
    $stderr.puts JSON.pretty_generate(
      error: 'unexpected_error',
      message: e.message,
      operation: operation_name
    )
    exit 1
  end
end

PluginConfig.run(ARGV.dup) if __FILE__ == $PROGRAM_NAME
