require "minitest/autorun"
require_relative "../lib/util"

class TestUtilParseAusDate < Minitest::Test
  # --- Standard formats ---

  def test_dd_mm_yyyy
    assert_equal Date.new(2025, 3, 15), Util.parse_aus_date("15/03/2025")
  end

  def test_dd_mm_yy
    assert_equal Date.new(2025, 8, 1), Util.parse_aus_date("01/08/25")
  end

  def test_natural_language_date
    assert_equal Date.new(2025, 6, 20), Util.parse_aus_date("20 June 2025")
  end

  def test_abbreviated_month
    assert_equal Date.new(2025, 4, 5), Util.parse_aus_date("5 Apr 2025")
  end

  def test_iso_format
    assert_equal Date.new(2025, 12, 1), Util.parse_aus_date("2025-12-01")
  end

  # --- Edge cases ---

  def test_nil_returns_nil
    assert_nil Util.parse_aus_date(nil)
  end

  def test_empty_string_returns_nil
    assert_nil Util.parse_aus_date("")
  end

  def test_whitespace_only_returns_nil
    assert_nil Util.parse_aus_date("   ")
  end

  def test_garbage_returns_nil
    assert_nil Util.parse_aus_date("not a date")
  end

  def test_partial_date_returns_nil
    assert_nil Util.parse_aus_date("15/03")
  end

  def test_strips_whitespace
    assert_equal Date.new(2025, 3, 15), Util.parse_aus_date("  15/03/2025  ")
  end

  # --- Ambiguity: dd/mm not mm/dd ---
  # 01/02/2025 should be February 1st, not January 2nd

  def test_day_month_order
    result = Util.parse_aus_date("01/02/2025")
    assert_equal 2, result.month, "Expected month 2 (February), got #{result.month}"
    assert_equal 1, result.day
  end
end

class TestUtilParseEpochMs < Minitest::Test
  def test_known_timestamp
    # 2025-01-01 00:00:00 UTC in ms
    ms = Date.new(2025, 1, 1).to_time.to_i * 1000
    assert_equal Date.new(2025, 1, 1), Util.parse_epoch_ms(ms)
  end

  def test_string_input
    ms = Date.new(2024, 6, 15).to_time.to_i * 1000
    assert_equal Date.new(2024, 6, 15), Util.parse_epoch_ms(ms.to_s)
  end

  def test_nil_returns_nil
    assert_nil Util.parse_epoch_ms(nil)
  end

  def test_empty_string_returns_nil
    assert_nil Util.parse_epoch_ms("")
  end

  def test_zero_returns_a_date
    # epoch 0 = 1970-01-01 (valid, should not raise)
    result = Util.parse_epoch_ms(0)
    refute_nil result
  end
end

class TestUtilRefToTable < Minitest::Test
  def test_known_planbuild_ref
    # "DA-HOB-2025-1234" -> "da_hobartcity"
    assert_equal "da_hobartcity", Util.ref_to_table("DA-HOB-2025-1234")
  end

  def test_launceston_ref
    assert_equal "da_launceston", Util.ref_to_table("DA-LAU-2024-99")
  end

  def test_case_insensitive_code
    assert_equal "da_hobartcity", Util.ref_to_table("DA-hob-2025-1")
  end

  def test_unknown_code_raises
    assert_raises(RuntimeError) { Util.ref_to_table("DA-ZZZ-2025-1") }
  end
end

class TestUtilCouncilMap < Minitest::Test
  def test_all_council_map_values_start_with_da
    Util::COUNCIL_MAP.each do |key, table|
      assert table.start_with?("da_"),
        "COUNCIL_MAP[#{key.inspect}] = #{table.inspect} does not start with 'da_'"
    end
  end

  def test_all_planbuild_codes_map_to_known_councils
    Util::PLANBUILD_CODE_MAP.each do |code, council_key|
      assert Util::COUNCIL_MAP.key?(council_key),
        "PLANBUILD_CODE_MAP[#{code.inspect}] = #{council_key.inspect} has no entry in COUNCIL_MAP"
    end
  end
end
