# frozen_string_literal: true

require "json"
require "asciidoctor-latexmath"

class CollisionLogger
  attr_reader :warnings

  def initialize
    @warnings = []
  end

  def warn(message = nil, &block)
    @warnings << (message || block&.call)
  end

  def info(*)
  end

  def error(*)
  end

  def debug(*)
  end
end

RSpec.describe "Hash collision avoidance" do
  let(:hash_prefix) { "0123456789abcdef" }
  let(:hash_one) { hash_prefix + ("0" * 48) }
  let(:hash_two) { hash_prefix + ("1" * 48) }

  it "upgrades autogenerated targets to 32 characters when 16-character prefix collides" do
    original_logger = Asciidoctor::LoggerManager.logger
    logger = CollisionLogger.new
    Asciidoctor::LoggerManager.logger = logger

    original_hexdigest = Digest::SHA256.method(:hexdigest)

    allow(Digest::SHA256).to receive(:hexdigest) do |input|
      case input
      when "COLLISION-A"
        hash_one
      when "COLLISION-B"
        hash_two
      else
        original_hexdigest.call(input)
      end
    end

    within_tmpdir do |dir|
      Dir.chdir(dir) do
        stub_tool_availability(dvisvgm: true, pdf2svg: false)

        source = <<~ADOC
          [latexmath]
          ++++
          COLLISION-A
          ++++

          [latexmath]
          ++++
          COLLISION-B
          ++++
        ADOC

        convert_with_extension(source, attributes: {"imagesdir" => "images"})

        generated = Dir.glob("images/*.svg").map { |path| File.basename(path) }
        expect(generated).to include("lm-#{hash_prefix}.svg")
        expect(generated).to include("lm-#{hash_prefix}1111111111111111.svg")

        collision_warning = logger.warnings.find { |msg| msg.include?("lm-#{hash_prefix}") && msg.include?("lm-#{hash_prefix}1111111111111111") }
        expect(collision_warning).not_to be_nil

        metadata_hashes = Dir.glob(".asciidoctor/latexmath/**/metadata.json").map do |metadata_path|
          JSON.parse(File.read(metadata_path)).fetch("content_hash")
        end
        expect(metadata_hashes).to include(hash_one, hash_two)
        metadata_hashes.each do |value|
          expect(value.length).to eq(64)
        end
      end
    end
  ensure
    Asciidoctor::LoggerManager.logger = original_logger
  end
end
