defmodule Microwaveprop.AccountsFixtures do
  @moduledoc """
  This module defines test helpers for creating
  entities via the `Microwaveprop.Accounts` context.
  """

  import Ecto.Query

  alias Microwaveprop.Accounts
  alias Microwaveprop.Accounts.Scope
  alias Microwaveprop.Accounts.User
  alias Microwaveprop.Repo

  def unique_user_email, do: "user#{System.unique_integer([:positive])}@example.com"
  def unique_user_callsign, do: "W#{[:positive] |> System.unique_integer() |> rem(1_000_000)}X"
  def valid_user_password, do: "hello world!"

  def valid_user_attributes(attrs \\ %{}) do
    password = valid_user_password()

    Enum.into(attrs, %{
      callsign: unique_user_callsign(),
      name: "Test User",
      email: unique_user_email(),
      password: password,
      password_confirmation: password
    })
  end

  def unconfirmed_user_fixture(attrs \\ %{}) do
    {:ok, user} =
      attrs
      |> valid_user_attributes()
      |> Accounts.register_user()

    user
  end

  def user_fixture(attrs \\ %{}) do
    user = unconfirmed_user_fixture(attrs)

    {:ok, user} =
      user
      |> User.confirm_changeset()
      |> Repo.update()

    user
  end

  def user_scope_fixture do
    user = user_fixture()
    user_scope_fixture(user)
  end

  def user_scope_fixture(user) do
    Scope.for_user(user)
  end

  def extract_user_token(fun) do
    {:ok, captured_email} = fun.(&"[TOKEN]#{&1}[TOKEN]")
    [_, token | _] = String.split(captured_email.text_body, "[TOKEN]")
    token
  end

  def override_token_authenticated_at(token, authenticated_at) when is_binary(token) do
    Repo.update_all(
      from(t in Accounts.UserToken,
        where: t.token == ^token
      ),
      set: [authenticated_at: authenticated_at]
    )
  end

  def offset_user_token(token, amount_to_add, unit) do
    dt = DateTime.add(DateTime.utc_now(:second), amount_to_add, unit)

    Repo.update_all(
      from(ut in Accounts.UserToken, where: ut.token == ^token),
      set: [inserted_at: dt, authenticated_at: dt]
    )
  end
end
