class Pronto::Rustcov

def build_messages(grouped)

def build_messages(grouped)
  messages = []
  grouped.each do |patch, lines|
    linenos = lines.map(&:new_lineno).sort
    line_ranges = linenos.chunk_while { |i, j| j == i + 1 }.to_a
    best_ranges = line_ranges.sort_by { |range| [-range.size, range.first] }.take(pronto_messages_per_file_limit)
    # If we have a message per file limit of N, then create N individual messages
    # We'll take each range and create a separate message for it, up to the limit
    best_ranges.each do |range|
      message_text = format_message_text(range)
      # Find the first line in this range for the message
      first_line_in_range = lines.find { |line| line.new_lineno == range.first }
      messages << Pronto::Message.new(
        patch.new_file_path,
        first_line_in_range,
        :warning,
        message_text,
        nil,
        self.class
      )
    end
  end
  messages
end

def format_message_text(range)

def format_message_text(range)
  # Format the range as "start–end" or just the number if it's a single line
  formatted_range = range.size > 1 ? "#{range.first}#{range.last}" : range.first.to_s
  "⚠️ Test coverage is missing for lines: #{formatted_range}"
end

def group_patches(patches, lcov)

def group_patches(patches, lcov)
  grouped = Hash.new { |h, k| h[k] = [] }
  patches.each do |patch|
    next unless patch.added_lines.any?
    file_path = patch.new_file_full_path.to_s
    uncovered = lcov[file_path]
    next unless uncovered
    patch.added_lines.each do |line|
      if uncovered.include?(line.new_lineno)
        grouped[patch].push(line)
      end
    end
  end
  grouped.sort_by { |_, lines| -lines.count }.take(pronto_files_limit)
end

def lcov_path

def lcov_path
  ENV['PRONTO_RUSTCOV_LCOV_PATH'] || ENV['LCOV_PATH'] || 'target/lcov.info'
end

def one_message_per_file(lcov_path)

def one_message_per_file(lcov_path)
  return [] unless @patches
  lcov = parse_lcov(lcov_path)
  grouped = group_patches(@patches, lcov)
  build_messages(grouped)
end

def parse_lcov(path)

def parse_lcov(path)
  uncovered = Hash.new { |h, k| h[k] = [] }
  file = nil
  begin
    File.foreach(path) do |line|
      case line
      when /^SF:(.+)/
        file = File.expand_path($1.strip)
      when /^DA:(\d+),0$/
        uncovered[file] << $1.to_i if file
      when /^end_of_record/
        file = nil
      end
    end
  rescue Errno::ENOENT
    # File not found, raise a more informative error
    fail "LCOV file not found at #{path}. Make sure your Rust tests were run with coverage enabled."
  end
  uncovered
end

def pronto_files_limit

def pronto_files_limit
  ENV['PRONTO_RUSTCOV_FILES_LIMIT']&.to_i || 5
end

def pronto_messages_per_file_limit

def pronto_messages_per_file_limit
  ENV['PRONTO_RUSTCOV_MESSAGES_PER_FILE_LIMIT']&.to_i || 5
end

def run

def run
  one_message_per_file(lcov_path)
end