defmodule Mv.Vereinfacht.Changes.SyncContactTest do
  @moduledoc """
  Tests for Mv.Vereinfacht.Changes.SyncContact.

  When Vereinfacht is not configured, member create/update should succeed
  and vereinfacht_contact_id remains nil.
  """
  use Mv.DataCase, async: false

  alias Mv.Membership

  setup do
    clear_vereinfacht_env()
    :ok
  end

  describe "member create when Vereinfacht not configured" do
    test "member is created and vereinfacht_contact_id is nil" do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      attrs = %{
        first_name: "Sync",
        last_name: "Test",
        email: "sync_test_#{System.unique_integer([:positive])}@example.com"
      }

      assert {:ok, member} = Membership.create_member(attrs, actor: system_actor)
      assert member.vereinfacht_contact_id == nil
    end
  end

  describe "member update when Vereinfacht not configured" do
    test "member is updated and vereinfacht_contact_id is unchanged" do
      member = Mv.Fixtures.member_fixture()
      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      assert {:ok, updated} =
               Membership.update_member(member, %{first_name: "Updated"}, actor: system_actor)

      assert updated.vereinfacht_contact_id == nil
    end
  end

  describe "when Vereinfacht is configured" do
    # Regression: after_transaction callback receives 2 args (changeset, result), not 3.
    # If the callback had arity 3, create_member would raise BadArityError.
    # Also: Client must send JSON-encoded body (iodata); raw map causes ArgumentError
    # when the request is sent. With an unreachable URL we get :econnrefused before
    # that, so this test would not catch the iodata bug; a Bypass/stub server would.
    test "create_member succeeds and after_transaction runs without error (API may fail)" do
      set_vereinfacht_env()
      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      attrs = %{
        first_name: "API",
        last_name: "Test",
        email: "api_test_#{System.unique_integer([:positive])}@example.com",
        street: "Test St",
        postal_code: "12345",
        city: "Test City"
      }

      assert {:ok, member} = Membership.create_member(attrs, actor: system_actor)
      assert member.id
      # Sync may fail (e.g. connection refused), so contact_id can stay nil
    after
      clear_vereinfacht_env()
    end

    test "update_member succeeds and after_transaction runs without error (API may fail)" do
      set_vereinfacht_env()

      member =
        Mv.Fixtures.member_fixture(%{
          street: "Test St",
          postal_code: "12345",
          city: "Test City"
        })

      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      assert {:ok, updated} =
               Membership.update_member(member, %{first_name: "Updated"}, actor: system_actor)

      assert updated.id == member.id
    after
      clear_vereinfacht_env()
    end
  end

  defp set_vereinfacht_env do
    System.put_env("VEREINFACHT_API_URL", "http://127.0.0.1:1/api/v1")
    System.put_env("VEREINFACHT_API_KEY", "test-key")
    System.put_env("VEREINFACHT_CLUB_ID", "2")
  end

  defp clear_vereinfacht_env do
    System.delete_env("VEREINFACHT_API_URL")
    System.delete_env("VEREINFACHT_API_KEY")
    System.delete_env("VEREINFACHT_CLUB_ID")
  end
end
