defmodule Mv.EmailSync.Changes.SyncMemberEmailToUser do
  @moduledoc """
  Synchronizes Member.email → User.email

  Trigger conditions are configured in resources via `where` clauses:
  - Member resource: Use `where: [changing(:email)]`

  Used by Member resource for bidirectional email sync.
  """
  use Ash.Resource.Change
  alias Mv.EmailSync.{Helpers, Loader}

  @doc """
  Implements the email synchronization from Member to User.

  This function is called automatically by Ash when the configured trigger
  conditions are met (see `@moduledoc` for trigger details).

  ## Parameters
  - `changeset` - The Ash changeset being processed
  - `_opts` - Options passed to the change (unused)
  - `context` - Ash context map containing metadata (e.g., `:syncing_email` flag)

  ## Returns
  Modified changeset with email synchronization applied, or original changeset
  if recursion detected.
  """
  @impl true
  def change(changeset, _opts, context) do
    # Only recursion protection needed - trigger logic is in `where` clauses
    if Map.get(context, :syncing_email, false) do
      changeset
    else
      sync_email(changeset)
    end
  end

  defp sync_email(changeset) do
    new_email = Ash.Changeset.get_attribute(changeset, :email)

    Ash.Changeset.around_transaction(changeset, fn cs, callback ->
      result = callback.(cs)

      with {:ok, member} <- Helpers.extract_record(result),
           linked_user <- Loader.get_linked_user(member) do
        Helpers.sync_email_to_linked_record(result, linked_user, new_email)
      else
        _ -> result
      end
    end)
  end
end
