defmodule Mobilizon.Storage.Repo.Migrations.RepairUsersDefaultActors do
  use Ecto.Migration

  def up do
    rows = fetch_bad_rows()
    Enum.each(rows, &process_row/1)
  end

  def down do
    # Nothing to do
  end

  defp fetch_bad_rows() do
    %Postgrex.Result{rows: rows} =
      Ecto.Adapters.SQL.query!(
        Mobilizon.Storage.Repo,
        "SELECT u.id FROM users u JOIN actors a ON u.default_actor_id = a.id WHERE a.user_id IS NULL"
      )

    rows
  end

  defp process_row([user_id]) do
    user_id
    |> find_first_actor_id()
    |> repair_user_default_actor(user_id)
  end

  defp find_first_actor_id(user_id) do
    %Postgrex.Result{rows: [[id]]} =
      Ecto.Adapters.SQL.query!(
        Mobilizon.Storage.Repo,
        "SELECT id FROM actors WHERE user_id = $1 AND type = 'Person' AND NOT suspended ORDER BY id LIMIT 1",
        [user_id]
      )

    id
  end

  defp repair_user_default_actor(actor_id, user_id) do
    Ecto.Adapters.SQL.query!(
      Mobilizon.Storage.Repo,
      "UPDATE users SET default_actor_id = $1 WHERE id = $2",
      [actor_id, user_id]
    )
  end
end