# frozen_string_literal: true

require 'git/commands/base'

module Git
  module Commands
    module Stash
      # Show the changes recorded in a stash entry as a diff
      #
      # Shows the changes recorded in the stash entry as a diff between the
      # stashed contents and the commit back when the stash entry was first
      # created.
      #
      # @example Show numstat for the latest stash
      #   Git::Commands::Stash::Show.new(ctx).call(numstat: true, shortstat: true)
      #
      # @example Show patch for a specific stash
      #   Git::Commands::Stash::Show.new(ctx).call('stash@{2}', patch: true, numstat: true, shortstat: true)
      #
      # @example Show with directory statistics
      #   Git::Commands::Stash::Show.new(ctx).call(numstat: true, shortstat: true, dirstat: true)
      #   Git::Commands::Stash::Show.new(ctx).call(numstat: true, shortstat: true, dirstat: 'lines,cumulative')
      #
      # @note `arguments` block audited against https://git-scm.com/docs/git-stash/2.53.0
      #
      # @see Git::Commands::Stash Git::Commands::Stash for usage examples
      #
      # @see https://git-scm.com/docs/git-stash git-stash documentation
      #
      # @api private
      #
      class Show < Git::Commands::Base
        arguments do
          literal 'stash'
          literal 'show'

          flag_option :patch
          flag_option :numstat
          flag_option :raw
          flag_option :shortstat
          value_option %i[unified U], inline: true

          flag_option %i[include_untracked u], negatable: true
          flag_option :only_untracked
          flag_or_value_option %i[find_renames M], inline: true
          flag_or_value_option %i[find_copies C], inline: true
          flag_option :find_copies_harder
          value_option :inter_hunk_context, inline: true
          flag_or_value_option :dirstat, inline: true
          operand :stash
        end

        # @!method call(*, **options)
        #
        #   @param options [Hash] command options
        #
        #   @option options [Boolean, nil] :patch (nil) command option key; see overload docs
        #     for the full option list
        #
        #   @overload call(**options)
        #
        #     Show diff for the latest stash
        #
        #     @param options [Hash] command options
        #
        #     @option options [Boolean, nil] :patch (nil) include unified diff patches per file
        #
        #     @option options [Boolean, nil] :numstat (nil) include per-file insertion/deletion counts
        #
        #     @option options [Boolean, nil] :raw (nil) include per-file mode/SHA/status metadata
        #
        #     @option options [Boolean, nil] :shortstat (nil) include aggregate totals line
        #
        #     @option options [Integer, String] :unified (nil) generate diff with <n> lines of context
        #
        #       Alias: :U
        #
        #     @option options [Boolean, nil] :include_untracked (nil) include untracked files (`--include-untracked`)
        #
        #       Alias: :u
        #
        #     @option options [Boolean, nil] :no_include_untracked (nil) exclude untracked files
        #       (`--no-include-untracked`)
        #
        #     @option options [Boolean, nil] :only_untracked (nil) show only untracked files
        #
        #     @option options [Boolean, Integer, nil] :find_renames (nil) detect renames; optionally pass a
        #       similarity threshold (e.g., 50 for 50%). Alias: :M
        #
        #     @option options [Boolean, Integer, nil] :find_copies (nil) detect copies as well as renames;
        #       optionally pass a threshold. Alias: :C
        #
        #     @option options [Boolean, nil] :find_copies_harder (nil) inspect all files as copy sources; expensive
        #
        #     @option options [Integer, String] :inter_hunk_context (nil) show context between diff hunks, up to
        #       <n> lines, fusing hunks that are close to each other
        #
        #     @option options [Boolean, String, nil] :dirstat (nil) include directory statistics
        #
        #       Pass `true` for default, or a string like `'lines,cumulative'` for options.
        #
        #     @return [Git::CommandLine::Result] the result of calling `git stash show`
        #
        #   @overload call(stash, **options)
        #
        #     Show diff for a specific stash
        #
        #     @param stash [String] stash reference (e.g., 'stash@\\{0}', '0')
        #
        #     @param options [Hash] command options
        #
        #     @option options [Boolean, nil] :patch (nil) include unified diff patches per file
        #
        #     @option options [Boolean, nil] :numstat (nil) include per-file insertion/deletion counts
        #
        #     @option options [Boolean, nil] :raw (nil) include per-file mode/SHA/status metadata
        #
        #     @option options [Boolean, nil] :shortstat (nil) include aggregate totals line
        #
        #     @option options [Integer, String] :unified (nil) generate diff with <n> lines of context
        #
        #       Alias: :U
        #
        #     @option options [Boolean, nil] :include_untracked (nil) include untracked files (`--include-untracked`)
        #
        #       Alias: :u
        #
        #     @option options [Boolean, nil] :no_include_untracked (nil) exclude untracked files
        #       (`--no-include-untracked`)
        #
        #     @option options [Boolean, nil] :only_untracked (nil) show only untracked files
        #
        #     @option options [Boolean, Integer, nil] :find_renames (nil) detect renames; optionally pass a
        #       similarity threshold (e.g., 50 for 50%). Alias: :M
        #
        #     @option options [Boolean, Integer, nil] :find_copies (nil) detect copies as well as renames;
        #       optionally pass a threshold. Alias: :C
        #
        #     @option options [Boolean, nil] :find_copies_harder (nil) inspect all files as copy sources; expensive
        #
        #     @option options [Integer, String] :inter_hunk_context (nil) show context between diff hunks, up to
        #       <n> lines, fusing hunks that are close to each other
        #
        #     @option options [Boolean, String, nil] :dirstat (nil) include directory statistics
        #
        #       Pass `true` for default, or a string like `'lines,cumulative'` for options.
        #
        #     @return [Git::CommandLine::Result] the result of calling `git stash show`
        #
        #   @raise [ArgumentError] if unsupported options are provided
        #
        #   @raise [Git::FailedError] if git exits with a non-zero exit status
        #
        #   @api public
      end
    end
  end
end
