# `PhoenixKitEcommerce.Services.ImageDownloader`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ecommerce/blob/v0.1.8/lib/phoenix_kit_ecommerce/services/image_downloader.ex#L1)

Service for downloading images from external URLs and storing them in the Storage module.

Handles HTTP download with proper error handling, content type detection,
and integration with PhoenixKit.Modules.Storage for persistent storage.

## Usage

    # Download and store a single image
    {:ok, file_uuid} = ImageDownloader.download_and_store(url, user_uuid)

    # Download with options
    {:ok, file_uuid} = ImageDownloader.download_and_store(url, user_uuid, timeout: 30_000)

    # Batch download multiple images
    results = ImageDownloader.download_batch(urls, user_uuid)
    # => [{url, {:ok, file_uuid}}, {url, {:error, reason}}, ...]

# `download_and_store`

```elixir
@spec download_and_store(String.t(), String.t() | nil, keyword()) ::
  {:ok, String.t()} | {:error, atom() | String.t()}
```

Downloads an image from a URL and stores it in the Storage module.

Returns `{:ok, file_uuid}` where file_uuid is a UUID that can be used to reference
the stored file.

## Options

  * `:timeout` - HTTP request timeout in milliseconds (default: 30_000)
  * `:metadata` - Additional metadata to store with the file

## Examples

    iex> download_and_store("https://cdn.shopify.com/image.jpg", user_uuid)
    {:ok, "018f1234-5678-7890-abcd-ef1234567890"}

    iex> download_and_store("https://example.com/404.jpg", user_uuid)
    {:error, :not_found}

# `download_batch`

```elixir
@spec download_batch([String.t()], String.t() | nil, keyword()) :: [
  {String.t(), {:ok, String.t()} | {:error, atom() | String.t()}}
]
```

Downloads and stores multiple images in batch.

Returns a list of tuples `{url, result}` where result is either
`{:ok, file_uuid}` or `{:error, reason}`.

## Options

  * `:timeout` - HTTP request timeout for each image (default: 30_000)
  * `:concurrency` - Number of concurrent downloads (default: 5)
  * `:on_progress` - Callback function called after each download: `fn(url, result, index, total) -> :ok end`

## Examples

    iex> download_batch(["url1", "url2", "url3"], user_uuid)
    [{"url1", {:ok, "uuid-1"}}, {"url2", {:ok, "uuid-2"}}, {"url3", {:error, :timeout}}]

# `download_image`

```elixir
@spec download_image(
  String.t(),
  keyword()
) ::
  {:ok, String.t(), String.t(), non_neg_integer()}
  | {:error, atom() | String.t()}
```

Downloads an image from a URL to a temporary file.

Returns `{:ok, temp_path, content_type, size}` on success.

## Options

  * `:timeout` - HTTP request timeout in milliseconds (default: 30_000)

## Examples

    iex> download_image("https://example.com/image.jpg")
    {:ok, "/tmp/phx_img_abc123", "image/jpeg", 12345}

    iex> download_image("https://example.com/404.jpg")
    {:error, :not_found}

# `valid_image_url?`

```elixir
@spec valid_image_url?(String.t()) :: boolean()
```

Checks if a URL points to a valid image that can be downloaded.

Performs a HEAD request to verify the URL is accessible and returns
an image content type.

## Examples

    iex> valid_image_url?("https://example.com/image.jpg")
    true

    iex> valid_image_url?("https://example.com/document.pdf")
    false

# `validate_urls`

```elixir
@spec validate_urls(
  [String.t()],
  keyword()
) :: {[String.t()], [String.t()]}
```

Validates URLs are accessible before batch download.

Performs HEAD requests to verify URLs are accessible and return valid
image content types. Returns a tuple of `{valid_urls, invalid_urls}`.

## Options

  * `:timeout` - HTTP request timeout in milliseconds (default: 5_000)
  * `:concurrency` - Number of concurrent validations (default: 10)

## Examples

    iex> validate_urls(["https://example.com/image.jpg", "https://example.com/404.jpg"])
    {["https://example.com/image.jpg"], ["https://example.com/404.jpg"]}

---

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