defmodule Mv.Membership.MemberExportSortTest do
  use ExUnit.Case, async: true

  alias Mv.Membership.MemberExportSort

  describe "custom_field_sort_key/2" do
    test "nil has rank 1 (sorts last in asc, first in desc)" do
      assert MemberExportSort.custom_field_sort_key(:string, nil) == {1, nil}
      assert MemberExportSort.custom_field_sort_key(:date, nil) == {1, nil}
    end

    test "date: chronological key (ISO8601 string)" do
      earlier = ~D[2023-01-15]
      later = ~D[2024-06-01]
      assert MemberExportSort.custom_field_sort_key(:date, earlier) == {0, "2023-01-15"}
      assert MemberExportSort.custom_field_sort_key(:date, later) == {0, "2024-06-01"}
      assert {0, "2023-01-15"} < {0, "2024-06-01"}
    end

    test "date + nil: nil sorts after any date in asc" do
      key_date = MemberExportSort.custom_field_sort_key(:date, ~D[2024-01-01])
      key_nil = MemberExportSort.custom_field_sort_key(:date, nil)
      assert key_date == {0, "2024-01-01"}
      assert key_nil == {1, nil}
      assert key_date < key_nil
    end

    test "boolean: false < true" do
      key_f = MemberExportSort.custom_field_sort_key(:boolean, false)
      key_t = MemberExportSort.custom_field_sort_key(:boolean, true)
      assert key_f == {0, 0}
      assert key_t == {0, 1}
      assert key_f < key_t
    end

    test "boolean + nil: nil sorts after false and true in asc" do
      key_f = MemberExportSort.custom_field_sort_key(:boolean, false)
      key_t = MemberExportSort.custom_field_sort_key(:boolean, true)
      key_nil = MemberExportSort.custom_field_sort_key(:boolean, nil)
      assert key_f < key_nil and key_t < key_nil
    end

    test "integer: numerical key" do
      assert MemberExportSort.custom_field_sort_key(:integer, 10) == {0, 10}
      assert MemberExportSort.custom_field_sort_key(:integer, -5) == {0, -5}
      assert MemberExportSort.custom_field_sort_key(:integer, 0) == {0, 0}
      assert {0, -5} < {0, 0} and {0, 0} < {0, 10}
    end

    test "string: case-insensitive key (downcased)" do
      key_a = MemberExportSort.custom_field_sort_key(:string, "Anna")
      key_b = MemberExportSort.custom_field_sort_key(:string, "bert")
      assert key_a == {0, "anna"}
      assert key_b == {0, "bert"}
      assert key_a < key_b
    end

    test "email: case-insensitive key" do
      assert MemberExportSort.custom_field_sort_key(:email, "User@Example.com") ==
               {0, "user@example.com"}
    end

    test "Ash.Union value is unwrapped" do
      union = %Ash.Union{value: ~D[2024-01-01], type: :date}
      assert MemberExportSort.custom_field_sort_key(:date, union) == {0, "2024-01-01"}
    end
  end

  describe "key_lt/3" do
    test "asc: smaller key first, nil last" do
      k_nil = {1, nil}
      k_early = {0, "2023-01-01"}
      k_late = {0, "2024-01-01"}
      refute MemberExportSort.key_lt(k_nil, k_early, "asc")
      refute MemberExportSort.key_lt(k_nil, k_late, "asc")
      assert MemberExportSort.key_lt(k_early, k_late, "asc")
      assert MemberExportSort.key_lt(k_early, k_nil, "asc")
    end

    test "desc: larger key first, nil first" do
      k_nil = {1, nil}
      k_early = {0, "2023-01-01"}
      k_late = {0, "2024-01-01"}
      assert MemberExportSort.key_lt(k_nil, k_early, "desc")
      assert MemberExportSort.key_lt(k_nil, k_late, "desc")
      assert MemberExportSort.key_lt(k_late, k_early, "desc")
      refute MemberExportSort.key_lt(k_early, k_nil, "desc")
    end
  end
end
