require_relative "test_helper"
require "open3"
require "json"

class CliTest < Minitest::Test
  include AdrTestHelpers

  ADR_NEW = File.join(PLUGIN_ROOT, "bin", "adr-new")
  ADR_INIT = File.join(PLUGIN_ROOT, "bin", "adr-init")

  def run_new(root, input)
    out, err, status = Open3.capture3("ruby", ADR_NEW, "--root", root, stdin_data: JSON.generate(input))
    [out.strip, err, status]
  end

  def run_init(root)
    Open3.capture3("ruby", ADR_INIT, "--root", root)
  end

  def test_init_creates_dir_and_index_and_clears_suppress
    Dir.mktmpdir do |root|
      FileUtils.mkdir_p(File.join(root, ".os-adr"))
      File.write(File.join(root, ".os-adr", "suppress"), "")
      _out, _err, status = run_init(root)
      assert status.success?
      repo = Adr::Repository.new(root: root)
      assert repo.exists?
      refute File.exist?(File.join(root, ".os-adr", "suppress"))
    end
  end

  def test_init_is_idempotent_and_preserves_existing_adrs
    with_project("0001-a.md" => sample_adr) do |root|
      _out, _err, status = run_init(root)
      assert status.success?
      assert_includes File.read(Adr::Repository.new(root: root).index_path), "0001"
    end
  end

  def test_new_creates_templated_numbered_indexed_adr
    with_project("0001-a.md" => sample_adr(id: "0001")) do |root|
      out, err, status = run_new(root, title: "Use Postgres", context: "We need a DB.",
                                       decision: "Postgres.", consequences: "Ops.",
                                       alternatives: "SQLite.", affected_paths: ["db/"],
                                       affected_components: ["storage"])
      assert status.success?, err
      assert out.end_with?("0002-use-postgres.md")
      record = Adr::Record.parse(File.read(out))
      assert_equal "0002", record.id
      assert_equal "Accepted", record.status
      assert_equal "Use Postgres", record.title
      assert_equal ["db/"], record.frontmatter["affected-paths"]
      Adr::Record::SECTION_ORDER.each { |s| assert record.sections.key?(s), "missing section #{s}" }
      assert_includes File.read(Adr::Repository.new(root: root).index_path),
                      "[Use Postgres](0002-use-postgres.md)"
    end
  end

  def test_new_supersession_is_mechanical
    with_project("0004-old-way.md" => sample_adr(id: "0004", title: "Old way")) do |root|
      out, err, status = run_new(root, title: "New way", supersedes: "0004")
      assert status.success?, err
      new_record = Adr::Record.parse(File.read(out))
      assert_equal "0004", new_record.frontmatter["supersedes"]
      old = Adr::Repository.new(root: root).find("0004")
      assert_equal new_record.id, old.record.frontmatter["superseded-by"]
      assert_equal "Superseded", old.record.status
      index = File.read(Adr::Repository.new(root: root).index_path)
      assert_includes index, "| Superseded |"
      assert_includes index, "| Accepted |"
    end
  end

  def test_new_requires_title
    with_project do |root|
      _out, err, status = run_new(root, {})
      refute status.success?
      assert_includes err, "title"
    end
  end

  def test_new_fails_cleanly_without_init
    Dir.mktmpdir do |root|
      _out, err, status = run_new(root, title: "X")
      refute status.success?
      assert_includes err, "adr-init"
    end
  end
end
