defmodule BerrypodWeb.Admin.ProductShow do
  use BerrypodWeb, :live_view

  alias Berrypod.Products
  alias Berrypod.Products.{Product, ProductImage, ProductVariant}
  alias Berrypod.Cart
  alias BerrypodWeb.R

  @impl true
  def mount(%{"id" => id}, _session, socket) do
    case Products.get_product_with_preloads(id) do
      nil ->
        socket =
          socket
          |> put_flash(:error, "Product not found")
          |> push_navigate(to: ~p"/admin/products")

        {:ok, socket}

      product ->
        form =
          product
          |> Product.storefront_changeset(%{})
          |> to_form(as: "product")

        socket =
          socket
          |> assign(:page_title, product.title)
          |> assign(:product, product)
          |> assign(:form, form)
          |> assign(:save_status, :idle)

        {:ok, socket}
    end
  end

  @impl true
  def handle_event("validate_storefront", %{"product" => params}, socket) do
    form =
      socket.assigns.product
      |> Product.storefront_changeset(params)
      |> Map.put(:action, :validate)
      |> to_form(as: "product")

    {:noreply, assign(socket, form: form, save_status: :idle)}
  end

  @impl true
  def handle_event("save_storefront", %{"product" => params}, socket) do
    case Products.update_storefront(socket.assigns.product, params) do
      {:ok, updated} ->
        product = %{
          updated
          | provider_connection: socket.assigns.product.provider_connection,
            images: socket.assigns.product.images,
            variants: socket.assigns.product.variants
        }

        form =
          product
          |> Product.storefront_changeset(%{})
          |> to_form(as: "product")

        socket =
          socket
          |> assign(:product, product)
          |> assign(:form, form)
          |> assign(:save_status, :saved)

        {:noreply, socket}

      {:error, changeset} ->
        {:noreply, assign(socket, form: to_form(changeset, as: "product"), save_status: :error)}
    end
  end

  @impl true
  def handle_event("resync", _params, socket) do
    product = socket.assigns.product

    if product.provider_connection do
      Products.enqueue_sync(product.provider_connection)

      {:noreply, put_flash(socket, :info, "Sync queued for #{product.provider_connection.name}")}
    else
      {:noreply, put_flash(socket, :error, "No provider connection")}
    end
  end

  @impl true
  def render(assigns) do
    ~H"""
    <.header>
      <.link navigate={~p"/admin/products"} class="admin-back-link">
        &larr; Products
      </.link>
      <div class="admin-product-header">
        <span class="admin-product-title">{@product.title}</span>
        <.visibility_badge visible={@product.visible} />
        <.status_badge status={@product.status} />
      </div>
      <:actions>
        <.external_link
          :if={provider_edit_url(@product)}
          href={provider_edit_url(@product)}
          icon={false}
          class="admin-btn admin-btn-ghost admin-btn-sm"
        >
          Edit on {provider_label(@product)}
          <.icon name="hero-arrow-top-right-on-square-mini" class="size-4" />
        </.external_link>
        <.link
          navigate={R.product(@product.slug)}
          class="admin-btn admin-btn-ghost admin-btn-sm"
        >
          View on shop <.icon name="hero-arrow-top-right-on-square-mini" class="size-4" />
        </.link>
      </:actions>
    </.header>

    <%!-- images + details --%>
    <div class="admin-product-grid">
      <div>
        <div class="admin-product-image-grid">
          <div
            :for={image <- sorted_images(@product)}
            class="admin-product-image-tile"
          >
            <img
              src={ProductImage.url(image, 400)}
              alt={image.alt || @product.title}
              loading="lazy"
            />
          </div>
        </div>
        <p
          :if={@product.images == []}
          class="admin-help-text"
        >
          No images
        </p>
      </div>

      <div class="admin-card">
        <div class="admin-card-body">
          <h3 class="admin-card-title">Details</h3>
          <.list>
            <:item :if={@product.provider_connection} title="Provider">
              {provider_label(@product)} via {@product.provider_connection.name}
            </:item>
            <:item title="Category">{@product.category || "—"}</:item>
            <:item title="Price">{Cart.format_price(@product.cheapest_price)}</:item>
            <:item title="Variants">{length(@product.variants)}</:item>
            <:item title="Images">{length(@product.images)}</:item>
            <:item title="Created">{format_date(@product.inserted_at)}</:item>
            <:item
              :if={@product.provider_connection && @product.provider_connection.last_synced_at}
              title="Last synced"
            >
              {format_date(@product.provider_connection.last_synced_at)}
            </:item>
          </.list>
        </div>
      </div>
    </div>

    <%!-- storefront controls --%>
    <div class="admin-card admin-card-spaced">
      <div class="admin-card-body">
        <h3 class="admin-card-title">Storefront controls</h3>
        <.form
          for={@form}
          phx-submit="save_storefront"
          phx-change="validate_storefront"
          class="admin-filter-row-end"
        >
          <label class="admin-filter-select">
            <span class="admin-filter-label">
              Visibility
            </span>
            <select
              name="product[visible]"
              class="admin-select admin-select-sm"
              aria-label="Visibility"
            >
              <option
                value="true"
                selected={@form[:visible].value == true || @form[:visible].value == "true"}
              >
                Visible
              </option>
              <option
                value="false"
                selected={@form[:visible].value == false || @form[:visible].value == "false"}
              >
                Hidden
              </option>
            </select>
          </label>
          <label class="admin-filter-select-wide">
            <span class="admin-filter-label">Category</span>
            <input
              type="text"
              name="product[category]"
              value={@form[:category].value}
              class="admin-input admin-input-sm"
              placeholder="e.g. Apparel"
            />
          </label>
          <.button type="submit" variant="primary" class="admin-btn-sm">Save</.button>
          <.inline_feedback status={@save_status} />
        </.form>
      </div>
    </div>

    <%!-- variants --%>
    <div class="admin-card admin-card-spaced">
      <div class="admin-card-body">
        <h3 class="admin-card-title">Variants ({length(@product.variants)})</h3>
        <.table id="variants" rows={@product.variants}>
          <:col :let={variant} label="Options">{ProductVariant.options_title(variant)}</:col>
          <:col :let={variant} label="SKU">{variant.sku || "—"}</:col>
          <:col :let={variant} label="Price">{Cart.format_price(variant.price)}</:col>
          <:col :let={variant} label="Cost">
            {if variant.cost, do: Cart.format_price(variant.cost), else: "—"}
          </:col>
          <:col :let={variant} label="Profit">
            {if ProductVariant.profit(variant),
              do: Cart.format_price(ProductVariant.profit(variant)),
              else: "—"}
          </:col>
          <:col :let={variant} label="Available">
            <span
              :if={variant.is_enabled && variant.is_available}
              class="admin-icon-positive"
            >
              <.icon name="hero-check-circle-mini" class="size-5" />
            </span>
            <span
              :if={!variant.is_enabled || !variant.is_available}
              class="admin-icon-muted"
            >
              <.icon name="hero-x-circle-mini" class="size-5" />
            </span>
          </:col>
        </.table>
      </div>
    </div>

    <%!-- provider data --%>
    <div :if={@product.provider_connection} class="admin-card admin-card-spaced">
      <div class="admin-card-body">
        <h3 class="admin-card-title">Provider data</h3>
        <.list>
          <:item title="Provider">
            {provider_label(@product)} via {@product.provider_connection.name}
          </:item>
          <:item title="Provider product ID">{@product.provider_product_id}</:item>
          <:item title="Status">{@product.status}</:item>
          <:item title="Sync status">{@product.provider_connection.sync_status}</:item>
        </.list>
        <div class="admin-section-body">
          <button phx-click="resync" class="admin-btn admin-btn-outline admin-btn-sm">
            <.icon name="hero-arrow-path" class="size-4" /> Re-sync
          </button>
        </div>
      </div>
    </div>
    """
  end

  # ---------------------------------------------------------------------------
  # Helpers
  # ---------------------------------------------------------------------------

  defp sorted_images(product) do
    (product.images || []) |> Enum.sort_by(& &1.position)
  end

  defp visibility_badge(assigns) do
    {color, label} =
      if assigns.visible do
        {"green", "visible"}
      else
        {"zinc", "hidden"}
      end

    assigns = assign(assigns, color: color, label: label)

    ~H"""
    <span class={["admin-status-pill", "admin-status-pill-#{@color}"]}>{@label}</span>
    """
  end

  defp status_badge(assigns) do
    color =
      case assigns.status do
        "active" -> "green"
        "draft" -> "amber"
        _ -> "zinc"
      end

    assigns = assign(assigns, :color, color)

    ~H"""
    <span class={["admin-status-pill", "admin-status-pill-#{@color}"]}>{@status}</span>
    """
  end

  defp provider_label(%{provider_connection: %{provider_type: "printify"}}), do: "Printify"
  defp provider_label(%{provider_connection: %{provider_type: "printful"}}), do: "Printful"
  defp provider_label(%{provider_connection: %{provider_type: type}}), do: String.capitalize(type)
  defp provider_label(_), do: nil

  defp provider_edit_url(%{
         provider_connection: %{provider_type: "printify", config: config},
         provider_product_id: pid
       }) do
    shop_id = config["shop_id"]
    if shop_id && pid, do: "https://printify.com/app/editor/#{shop_id}/#{pid}"
  end

  defp provider_edit_url(%{
         provider_connection: %{provider_type: "printful"},
         provider_product_id: pid
       }) do
    if pid, do: "https://www.printful.com/dashboard/sync/update?id=#{pid}"
  end

  defp provider_edit_url(_), do: nil

  defp format_date(nil), do: "—"
  defp format_date(datetime), do: Calendar.strftime(datetime, "%d %b %Y %H:%M")
end
