# frozen_string_literal: true

require_relative 'test_helper'
require 'open3'
require 'tmpdir'
require 'fileutils'

class TestValidateMarketplaces < Minitest::Test
  include TestHelpers

  SCRIPT_PATH = File.expand_path('../../validate_marketplaces.rb', __dir__)

  def setup
    @tmpdir = Dir.mktmpdir('validate_marketplaces_test')
  end

  def teardown
    FileUtils.rm_rf(@tmpdir) if @tmpdir && Dir.exist?(@tmpdir)
  end

  # Builds <root>/.claude-plugin/marketplace.json plus one passing plugin
  # (good-plugin) and one failing plugin (bad-plugin, missing plugin.json).
  def build_marketplace_root(root)
    FileUtils.mkdir_p(File.join(root, '.claude-plugin'))

    good_dir = File.join(root, 'good-plugin')
    create_plugin_json(good_dir, name: 'good-plugin', description: 'A good plugin')
    FileUtils.mkdir_p(File.join(good_dir, 'skills'))

    bad_dir = File.join(root, 'bad-plugin')
    FileUtils.mkdir_p(bad_dir) # no plugin.json at all -> fails check_plugin_json

    marketplace_data = {
      'name' => File.basename(root),
      'plugins' => [
        { 'name' => 'good-plugin', 'source' => './good-plugin', 'description' => 'A good plugin' },
        { 'name' => 'bad-plugin', 'source' => './bad-plugin', 'description' => 'A bad plugin' }
      ]
    }
    File.write(File.join(root, '.claude-plugin', 'marketplace.json'), JSON.pretty_generate(marketplace_data))
  end

  def build_all_passing_root(root)
    FileUtils.mkdir_p(File.join(root, '.claude-plugin'))

    good_dir = File.join(root, 'good-plugin')
    create_plugin_json(good_dir, name: 'good-plugin', description: 'A good plugin')
    FileUtils.mkdir_p(File.join(good_dir, 'skills'))

    marketplace_data = {
      'name' => File.basename(root),
      'plugins' => [
        { 'name' => 'good-plugin', 'source' => './good-plugin', 'description' => 'A good plugin' }
      ]
    }
    File.write(File.join(root, '.claude-plugin', 'marketplace.json'), JSON.pretty_generate(marketplace_data))
  end

  def run_script(*args)
    Open3.capture3('ruby', SCRIPT_PATH, *args)
  end

  def test_no_args_prints_usage_and_exits_2
    stdout, _stderr, status = run_script

    assert_equal 2, status.exitstatus
    assert_match(/Usage: ruby validate_marketplaces\.rb/, stdout)
    assert_match(%r{ruby .*validate_marketplaces\.rb .*/home/jared/dev/cc-plugins .*/home/jared/dev/cc-os}, stdout)
  end

  def test_all_passing_marketplace_exits_0
    root = File.join(@tmpdir, 'passing-root')
    build_all_passing_root(root)

    stdout, stderr, status = run_script(root)

    assert status.success?, "Expected exit 0, got #{status.exitstatus}. stdout: #{stdout} stderr: #{stderr}"
    assert_match(/PASS\s+good-plugin/, stdout)
    assert_match(/TOTAL: 1 plugin\(s\) checked, 1 passed, 0 failed/, stdout)
  end

  def test_mixed_marketplace_reports_pass_and_fail_and_exits_1
    root = File.join(@tmpdir, 'mixed-root')
    build_marketplace_root(root)

    stdout, _stderr, status = run_script(root)

    assert_equal 1, status.exitstatus
    assert_match(/PASS\s+good-plugin/, stdout)
    assert_match(/FAIL\s+bad-plugin/, stdout)
    assert_match(/TOTAL: 2 plugin\(s\) checked, 1 passed, 1 failed/, stdout)
  end

  def test_missing_marketplace_file_exits_2
    root = File.join(@tmpdir, 'empty-root')
    FileUtils.mkdir_p(root)

    stdout, _stderr, status = run_script(root)

    assert_equal 2, status.exitstatus
    assert_match(/ERROR: marketplace\.json not found/, stdout)
  end

  def test_mixed_marketplace_output_collapses_to_one_line_per_failure
    root = File.join(@tmpdir, 'mixed-root-collapse')
    build_marketplace_root(root)

    stdout, _stderr, _status = run_script(root)

    # bad-plugin fails multiple checks (missing plugin.json cascades into
    # several "Cannot check..." failures); only the first issue should
    # appear, on the same line as the FAIL marker, not as a multi-line dump.
    fail_lines = stdout.lines.select { |l| l =~ /FAIL\s+bad-plugin/ }
    assert_equal 1, fail_lines.size
    assert_match(/FAIL\s+bad-plugin - plugin\.json not found/, fail_lines.first)
    refute_match(/Cannot check required fields/, stdout)
  end

  def test_multiple_roots_one_failing_reports_both_and_exits_1
    root1 = File.join(@tmpdir, 'root1-pass')
    root2 = File.join(@tmpdir, 'root2-mixed')
    build_all_passing_root(root1)
    build_marketplace_root(root2)

    stdout, _stderr, status = run_script(root1, root2)

    assert_equal 1, status.exitstatus
    assert_match(/== #{Regexp.escape(File.expand_path(root1))} ==/, stdout)
    assert_match(/== #{Regexp.escape(File.expand_path(root2))} ==/, stdout)
    assert_match(/PASS\s+good-plugin/, stdout)
    assert_match(/FAIL\s+bad-plugin/, stdout)
    assert_match(/TOTAL: 3 plugin\(s\) checked, 2 passed, 1 failed/, stdout)
  end

  def test_multiple_roots_are_all_reported
    root1 = File.join(@tmpdir, 'root1')
    root2 = File.join(@tmpdir, 'root2')
    build_all_passing_root(root1)
    build_all_passing_root(root2)

    stdout, _stderr, status = run_script(root1, root2)

    assert status.success?
    assert_match(/== #{Regexp.escape(File.expand_path(root1))} ==/, stdout)
    assert_match(/== #{Regexp.escape(File.expand_path(root2))} ==/, stdout)
    assert_match(/TOTAL: 2 plugin\(s\) checked, 2 passed, 0 failed/, stdout)
  end
end
