# frozen_string_literal: true

require_relative 'test_helper'

class TestRuntimeVerifier < Minitest::Test
  # Hand-rolled fake status object; stands in for the Process::Status
  # returned by Open3.capture3. Minitest 6 moved Minitest::Mock out of
  # core (into the minitest-mock gem), so we avoid it entirely here.
  FakeStatus = Struct.new(:success) do
    def success?
      success
    end
  end

  # ─── snapshot (injected capture3) ─────────────────────────────────────

  def test_snapshot_parses_output_into_plugin_hash
    mock_output = <<~OUTPUT
      my-plugin@marketplace    enabled
      other-plugin@marketplace    disabled
    OUTPUT

    verifier = verifier_with_capture3(mock_output, success: true)
    result = verifier.snapshot
    assert_equal 'enabled', result['my-plugin@marketplace']
    assert_equal 'disabled', result['other-plugin@marketplace']
  end

  def test_snapshot_returns_empty_hash_on_failure
    verifier = verifier_with_capture3('', success: false)
    result = verifier.snapshot
    assert_equal({}, result)
  end

  def test_snapshot_returns_empty_hash_when_command_not_found
    verifier = PluginConfig::RuntimeVerifier.new(
      capture3: ->(*_args) { raise Errno::ENOENT, 'claude' }
    )
    result = verifier.snapshot
    assert_equal({}, result)
  end

  # ─── verify_status (injected capture3) ────────────────────────────────

  def test_verify_status_with_matching_status_returns_ok
    mock_output = "my-plugin@marketplace    enabled\n"

    verifier = verifier_with_capture3(mock_output, success: true)
    result = verifier.verify_status('my-plugin@marketplace', 'enabled')
    assert result[:verified]
  end

  def test_verify_status_with_mismatched_status_returns_not_ok
    mock_output = "my-plugin@marketplace    disabled\n"

    verifier = verifier_with_capture3(mock_output, success: true)
    result = verifier.verify_status('my-plugin@marketplace', 'enabled')
    refute result[:verified]
    assert_match(/expected 'enabled', got 'disabled'/, result[:details])
  end

  def test_verify_status_missing_plugin_returns_not_present
    verifier = verifier_with_capture3('', success: true)
    result = verifier.verify_status('missing@marketplace', 'enabled')
    refute result[:verified]
    assert_match(/not_present/, result[:details])
  end

  # ─── self.diff ───────────────────────────────────────────────────────

  def test_diff_identifies_changes
    before = { 'a@m' => 'enabled', 'b@m' => 'enabled' }
    after  = { 'a@m' => 'disabled', 'b@m' => 'enabled', 'c@m' => 'enabled' }

    result = PluginConfig::RuntimeVerifier.diff(before, after)

    assert_equal 2, result[:changed]    # a changed, c added
    assert_equal 1, result[:unchanged]  # b unchanged
  end

  def test_diff_identical_snapshots_returns_empty_changes
    snap = { 'a@m' => 'enabled', 'b@m' => 'disabled' }

    result = PluginConfig::RuntimeVerifier.diff(snap, snap)

    assert_equal 0, result[:changed]
    assert_equal 2, result[:unchanged]
  end

  private

  def verifier_with_capture3(stdout, success:)
    status = FakeStatus.new(success)
    PluginConfig::RuntimeVerifier.new(capture3: ->(*_args) { [stdout, '', status] })
  end
end
