defmodule SimpleshopTheme.Products.ProductImage do
  @moduledoc """
  Schema for product images.

  Images are ordered by position and belong to a single product.
  """

  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

  schema "product_images" do
    field :src, :string
    field :position, :integer, default: 0
    field :alt, :string
    field :image_id, :binary_id

    belongs_to :product, SimpleshopTheme.Products.Product
    belongs_to :image, SimpleshopTheme.Media.Image, define_field: false

    timestamps(type: :utc_datetime)
  end

  @doc """
  Changeset for creating or updating a product image.
  """
  def changeset(product_image, attrs) do
    product_image
    |> cast(attrs, [:product_id, :src, :position, :alt, :image_id])
    |> validate_required([:product_id, :src])
    |> foreign_key_constraint(:product_id)
    |> foreign_key_constraint(:image_id)
  end

  # ---------------------------------------------------------------------------
  # Display helpers
  # ---------------------------------------------------------------------------

  @doc """
  Returns the display URL for a product image at the given size.
  Prefers local image_id (responsive optimized), falls back to CDN src.
  """
  def display_url(image, size \\ 800)

  def display_url(%{image_id: id}, size) when not is_nil(id),
    do: "/images/#{id}/variant/#{size}.webp"

  def display_url(%{src: src}, _size) when is_binary(src), do: src
  def display_url(_, _), do: nil

  @doc """
  Returns a fully resolved URL for an image at the given size.
  Unlike `display_url/2`, handles mockup URL patterns that need size suffixes.
  Use for `<img>` tags where the URL must resolve to an actual file.
  """
  def direct_url(image, size \\ 800)

  def direct_url(%{image_id: id}, size) when not is_nil(id),
    do: "/images/#{id}/variant/#{size}.webp"

  def direct_url(%{src: "/mockups/" <> _ = src}, size), do: "#{src}-#{size}.webp"
  def direct_url(%{src: src}, _size) when is_binary(src), do: src
  def direct_url(_, _), do: nil

  @doc """
  Returns the source width from the linked Media.Image, if preloaded.
  """
  def source_width(%{image: %{source_width: w}}) when not is_nil(w), do: w
  def source_width(_), do: nil
end
