defmodule Berrypod.ProductsFixtures do
  @moduledoc """
  Test helpers for creating entities via the `Berrypod.Products` context.
  """

  alias Berrypod.Products

  def unique_provider_product_id, do: "prov_#{System.unique_integer([:positive])}"
  def unique_slug, do: "product-#{System.unique_integer([:positive])}"
  def unique_variant_id, do: "var_#{System.unique_integer([:positive])}"

  # Provider types to cycle through for unique constraint
  @provider_types ["printify", "gelato", "prodigi", "printful"]

  @doc """
  Returns valid attributes for a provider connection.
  Uses a unique provider type to avoid constraint violations.
  """
  def valid_provider_connection_attrs(attrs \\ %{}) do
    # Get a unique provider type if not specified
    provider_type = attrs[:provider_type] || unique_provider_type()

    Enum.into(attrs, %{
      provider_type: provider_type,
      name: "Test #{String.capitalize(provider_type)} Connection",
      enabled: true,
      api_key: "test_api_key_#{System.unique_integer([:positive])}",
      config: %{"shop_id" => "12345"}
    })
  end

  defp unique_provider_type do
    # Use modulo to cycle through provider types
    idx = rem(System.unique_integer([:positive]), length(@provider_types))
    Enum.at(@provider_types, idx)
  end

  @doc """
  Creates a provider connection fixture.

  Since provider_type has a unique constraint, this will reuse an existing
  connection of the same type if one exists.
  """
  def provider_connection_fixture(attrs \\ %{}) do
    provider_type = attrs[:provider_type] || unique_provider_type()

    # Try to find existing connection of this type first
    case Products.get_provider_connection_by_type(provider_type) do
      nil ->
        {:ok, conn} =
          attrs
          |> Map.put(:provider_type, provider_type)
          |> valid_provider_connection_attrs()
          |> Products.create_provider_connection()

        conn

      existing ->
        # Return existing connection (update if attrs differ)
        if map_size(Map.delete(attrs, :provider_type)) > 0 do
          {:ok, updated} = Products.update_provider_connection(existing, attrs)
          updated
        else
          existing
        end
    end
  end

  @doc """
  Returns valid attributes for a product.
  """
  def valid_product_attrs(attrs \\ %{}) do
    Enum.into(attrs, %{
      provider_product_id: unique_provider_product_id(),
      title: "Test Product",
      description: "A test product description",
      slug: unique_slug(),
      status: "active",
      visible: true,
      category: "Apparel",
      provider_data: %{"blueprint_id" => 145, "print_provider_id" => 29}
    })
  end

  @doc """
  Creates a product fixture.
  Automatically creates a provider connection if not provided.
  """
  def product_fixture(attrs \\ %{}) do
    conn = attrs[:provider_connection] || provider_connection_fixture()

    {:ok, product} =
      attrs
      |> Map.delete(:provider_connection)
      |> valid_product_attrs()
      |> Map.put(:provider_connection_id, conn.id)
      |> Products.create_product()

    product
  end

  @doc """
  Returns valid attributes for a product image.
  """
  def valid_product_image_attrs(attrs \\ %{}) do
    Enum.into(attrs, %{
      src: "https://example.com/image-#{System.unique_integer([:positive])}.jpg",
      position: 0,
      alt: "Product image"
    })
  end

  @doc """
  Creates a product image fixture.
  """
  def product_image_fixture(attrs \\ %{}) do
    product = attrs[:product] || product_fixture()

    {:ok, image} =
      attrs
      |> Map.delete(:product)
      |> valid_product_image_attrs()
      |> Map.put(:product_id, product.id)
      |> Products.create_product_image()

    image
  end

  @doc """
  Returns valid attributes for a product variant.
  """
  def valid_product_variant_attrs(attrs \\ %{}) do
    Enum.into(attrs, %{
      provider_variant_id: unique_variant_id(),
      title: "Medium / Black",
      sku: "TEST-SKU-#{System.unique_integer([:positive])}",
      price: 2500,
      compare_at_price: nil,
      cost: 1200,
      options: %{"Size" => "Medium", "Color" => "Black"},
      is_enabled: true,
      is_available: true
    })
  end

  @doc """
  Creates a product variant fixture.
  """
  def product_variant_fixture(attrs \\ %{}) do
    product = attrs[:product] || product_fixture()

    {:ok, variant} =
      attrs
      |> Map.delete(:product)
      |> valid_product_variant_attrs()
      |> Map.put(:product_id, product.id)
      |> Products.create_product_variant()

    variant
  end

  @doc """
  Creates a complete product fixture with images and variants.
  """
  def complete_product_fixture(attrs \\ %{}) do
    conn = attrs[:provider_connection] || provider_connection_fixture()
    product = product_fixture(Map.put(attrs, :provider_connection, conn))

    # Create images
    for i <- 0..1 do
      product_image_fixture(%{
        product: product,
        position: i,
        src: "https://example.com/#{product.slug}-#{i}.jpg"
      })
    end

    # Create variants
    for size <- ["Small", "Medium", "Large"], color <- ["Black", "White"] do
      product_variant_fixture(%{
        product: product,
        title: "#{size} / #{color}",
        options: %{"Size" => size, "Color" => color},
        price: if(size == "Large", do: 2800, else: 2500)
      })
    end

    # Return product with preloaded associations
    Berrypod.Repo.preload(product, [:images, :variants])
  end

  @doc """
  Returns a sample Printify product API response for testing normalization.
  """
  def printify_product_response do
    %{
      "id" => "12345",
      "title" => "Classic T-Shirt",
      "description" => "A comfortable cotton t-shirt",
      "blueprint_id" => 145,
      "print_provider_id" => 29,
      "tags" => ["apparel", "clothing"],
      "options" => [
        %{
          "name" => "Colors",
          "type" => "color",
          "values" => [
            %{"id" => 751, "title" => "Solid White"},
            %{"id" => 752, "title" => "Black"}
          ]
        },
        %{
          "name" => "Sizes",
          "type" => "size",
          "values" => [
            %{"id" => 2, "title" => "S"},
            %{"id" => 3, "title" => "M"},
            %{"id" => 4, "title" => "L"}
          ]
        }
      ],
      "variants" => [
        %{
          "id" => 100,
          "title" => "Solid White / S",
          "sku" => "TSH-WH-S",
          "price" => 2500,
          "cost" => 1200,
          "options" => [751, 2],
          "is_enabled" => true,
          "is_available" => true
        },
        %{
          "id" => 101,
          "title" => "Black / M",
          "sku" => "TSH-BK-M",
          "price" => 2500,
          "cost" => 1200,
          "options" => [752, 3],
          "is_enabled" => true,
          "is_available" => true
        }
      ],
      "images" => [
        %{"src" => "https://printify.com/img1.jpg", "position" => 0},
        %{"src" => "https://printify.com/img2.jpg", "position" => 1}
      ]
    }
  end
end
