defmodule Mix.Tasks.Berrypod.BackfillAltText do
  @shortdoc "Backfill alt text on existing images"
  @moduledoc """
  One-time task to populate alt text on images that were uploaded before
  the alt field existed.

  - Product images: copies alt from `product_images.alt`, falls back to product title
  - Logo: uses site name from theme settings
  - Header: "Header background"
  - Icon: "Site icon"
  - Skips images that already have alt text set

  ## Usage

      mix berrypod.backfill_alt_text
  """

  use Mix.Task

  alias Berrypod.Repo
  alias Berrypod.Media.Image
  alias Berrypod.Products.ProductImage
  alias Berrypod.Products.Product

  import Ecto.Query

  @impl true
  def run(_args) do
    Mix.Task.run("app.start")

    backfill_product_images()
    backfill_theme_images()

    Mix.shell().info("Alt text backfill complete.")
  end

  defp backfill_product_images do
    # Find product images with linked image records missing alt text
    results =
      from(pi in ProductImage,
        join: i in Image,
        on: i.id == pi.image_id,
        join: p in Product,
        on: p.id == pi.product_id,
        where: is_nil(i.alt) and not is_nil(pi.image_id),
        select: {i.id, pi.alt, p.title}
      )
      |> Repo.all()

    count =
      Enum.reduce(results, 0, fn {image_id, pi_alt, product_title}, acc ->
        alt = pi_alt || product_title || "Product image"

        from(i in Image, where: i.id == ^image_id)
        |> Repo.update_all(set: [alt: alt])

        acc + 1
      end)

    Mix.shell().info("  Updated #{count} product image(s)")
  end

  defp backfill_theme_images do
    theme = Berrypod.Settings.get_theme_settings()

    mapping = [
      {theme.logo_image_id, theme.site_name || "Shop logo"},
      {theme.header_image_id, "Header background"},
      {theme.icon_image_id, "Site icon"}
    ]

    count =
      Enum.reduce(mapping, 0, fn {image_id, alt}, acc ->
        if image_id do
          {updated, _} =
            from(i in Image, where: i.id == ^image_id and is_nil(i.alt))
            |> Repo.update_all(set: [alt: alt])

          acc + updated
        else
          acc
        end
      end)

    Mix.shell().info("  Updated #{count} theme image(s)")
  end
end
