# `Stancer.Auth`

3D Secure (Strong Customer Authentication) configuration helper.

Provides utilities to create and manage authentication requirements for payments.
Inspired by Stancer's Python library, this module accepts multiple formats for auth:

- String URL → automatically converts to auth object
- Boolean true → minimal auth object
- Boolean false → disables auth (returns nil)
- Map object → uses as-is

## Examples

### Simple string URL (most common)
```elixir
auth = Stancer.Auth.coerce("https://myapp.com/payment/success")
# => %{"return_url" => "https://myapp.com/payment/success"}
```

### Using in create_payment
```elixir
{:ok, payment} = Stancer.create_payment(%{
  "amount" => 5000,
  "currency" => "EUR",
  "card" => card_token,
  "auth" => Stancer.Auth.coerce("https://myapp.com/success")
})
```

### Minimal auth (no return_url)
```elixir
auth = Stancer.Auth.coerce(true)
# => %{}
```

### Disable auth
```elixir
auth = Stancer.Auth.coerce(false)
# => nil
```

### Full auth object
```elixir
auth = Stancer.Auth.new(%{"return_url" => "https://myapp.com/success"})
# => %{"return_url" => "https://myapp.com/success"}
```

# `coerce`

```elixir
@spec coerce(String.t() | boolean() | map()) :: map() | nil
```

Convert various formats to a standard auth map.

Accepts multiple formats for convenience:
- **String** (URL) → `%{"return_url" => url}`
- **Boolean true** → `%{}` (minimal auth)
- **Boolean false** → `nil` (disable auth)
- **Map** → returns as-is

This pattern is inspired by Stancer's Python library for ergonomics.

Parameters:
- `value` (string | boolean | map) — Auth configuration in any accepted format

Returns: Normalized auth map or nil

Raises: `ArgumentError` if string is empty

Examples:
```elixir
Stancer.Auth.coerce("https://myapp.com/success")
# => %{"return_url" => "https://myapp.com/success"}

Stancer.Auth.coerce(true)
# => %{}

Stancer.Auth.coerce(false)
# => nil

Stancer.Auth.coerce(%{"return_url" => "https://myapp.com/success"})
# => %{"return_url" => "https://myapp.com/success"}
```

# `failed?`

```elixir
@spec failed?(map()) :: boolean()
```

Check if auth verification failed.

Returns true if 3D Secure verification was attempted but failed.

Parameters:
- `payment` (map) — Payment object returned from Stancer API

Returns: Boolean

# `new`

```elixir
@spec new(map() | nil) :: map() | nil
```

Create a new auth object with the given attributes.

Parameters:
- `attrs` (map, optional) — Auth attributes. Typically just `%{"return_url" => "..."}`.

Returns: A map representing the auth object, or nil if empty attrs.

Examples:
```elixir
Stancer.Auth.new(%{"return_url" => "https://myapp.com/success"})
# => %{"return_url" => "https://myapp.com/success"}

Stancer.Auth.new(%{})
# => %{}
```

# `redirect_url`

```elixir
@spec redirect_url(map(), keyword()) :: String.t() | nil
```

Extract redirect URL from payment auth response (if 3D Secure verification needed).

When Stancer requires 3D Secure verification, the payment response includes
`auth.redirect_url`. This helper safely extracts it.

Parameters:
- `payment` (map) — Payment object returned from Stancer API
- `opts` (keyword, optional) — Options (currently unused, for future extension)

Returns: The redirect URL string if present, nil otherwise

Examples:
```elixir
{:ok, payment} = Stancer.create_payment(%{...})

case Stancer.Auth.redirect_url(payment) do
  url when is_binary(url) -> redirect(conn, external: url)
  nil -> # No 3D Secure needed
end
```

# `requires_verification?`

```elixir
@spec requires_verification?(map()) :: boolean()
```

Check if payment auth requires 3D Secure verification.

Returns true if the bank requires the customer to verify their identity.

Parameters:
- `payment` (map) — Payment object returned from Stancer API

Returns: Boolean

Examples:
```elixir
{:ok, payment} = Stancer.create_payment(%{...})

if Stancer.Auth.requires_verification?(payment) do
  redirect(conn, external: Stancer.Auth.redirect_url(payment))
else
  # No verification needed, safe to capture
end
```

# `status`

```elixir
@spec status(map()) :: String.t() | nil
```

Get the current auth status.

Returns the status string from payment auth, or nil if not present.

Possible values:
- `"success"` — Verified or not required
- `"request"` — Verification required (has redirect_url)
- `"failed"` — Verification failed
- `"unavailable"` — Card doesn't support 3D Secure

Parameters:
- `payment` (map) — Payment object returned from Stancer API

Returns: Status string or nil

Examples:
```elixir
{:ok, payment} = Stancer.create_payment(%{...})

case Stancer.Auth.status(payment) do
  "request" -> redirect(conn, external: Stancer.Auth.redirect_url(payment))
  "success" -> capture_payment()
  "failed" -> show_error("Verification failed")
  _ -> :ok
end
```

# `success?`

```elixir
@spec success?(map()) :: boolean()
```

Check if auth is in success/ready state (no further action needed).

Returns true if payment is authorized and ready to capture.

Parameters:
- `payment` (map) — Payment object returned from Stancer API

Returns: Boolean

Examples:
```elixir
{:ok, payment} = Stancer.create_payment(%{...})

if Stancer.Auth.success?(payment) do
  Stancer.API.payments_update(payment["id"], %{"capture" => true})
end
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
