defmodule BerrypodWeb.Shop.Collection do
  use BerrypodWeb, :live_view

  alias Berrypod.{Pages, Pagination, Products}

  @sort_options [
    {"featured", "Featured"},
    {"newest", "Newest"},
    {"price_asc", "Price: Low to High"},
    {"price_desc", "Price: High to Low"},
    {"name_asc", "Name: A-Z"},
    {"name_desc", "Name: Z-A"}
  ]

  @impl true
  def mount(_params, _session, socket) do
    page = Pages.get_page("collection")

    socket =
      socket
      |> assign(:page, page)
      |> assign(:sort_options, @sort_options)
      |> assign(:current_sort, "featured")

    {:ok, socket}
  end

  @impl true
  def handle_params(%{"slug" => slug} = params, _uri, socket) do
    sort = params["sort"] || "featured"
    page_num = Pagination.parse_page(params)

    case load_collection(slug, sort, page_num) do
      {:ok, title, category, pagination} ->
        {:noreply,
         socket
         |> assign(:page_title, title)
         |> assign(:page_description, collection_description(title))
         |> assign(:og_url, BerrypodWeb.Endpoint.url() <> "/collections/#{slug}")
         |> assign(:collection_title, title)
         |> assign(:collection_slug, slug)
         |> assign(:current_category, category)
         |> assign(:current_sort, sort)
         |> assign(:pagination, pagination)
         |> assign(:products, pagination.items)}

      :not_found ->
        {:noreply,
         socket
         |> put_flash(:error, "Collection not found")
         |> push_navigate(to: ~p"/collections/all")}
    end
  end

  defp load_collection("all", sort, page) do
    pagination = Products.list_visible_products_paginated(sort: sort, page: page)
    {:ok, "All Products", nil, pagination}
  end

  defp load_collection("sale", sort, page) do
    pagination = Products.list_visible_products_paginated(on_sale: true, sort: sort, page: page)
    {:ok, "Sale", :sale, pagination}
  end

  defp load_collection(slug, sort, page) do
    case Enum.find(Products.list_categories(), &(&1.slug == slug)) do
      nil ->
        :not_found

      category ->
        pagination =
          Products.list_visible_products_paginated(
            category: category.name,
            sort: sort,
            page: page
          )

        {:ok, category.name, category, pagination}
    end
  end

  @impl true
  def handle_event("sort_changed", %{"sort" => sort}, socket) do
    slug =
      case socket.assigns.current_category do
        nil -> "all"
        :sale -> "sale"
        category -> category.slug
      end

    {:noreply, push_patch(socket, to: ~p"/collections/#{slug}?sort=#{sort}")}
  end

  defp collection_description("All Products"), do: "Browse our full range of products."
  defp collection_description("Sale"), do: "Browse our current sale items."
  defp collection_description(title), do: "Browse our #{String.downcase(title)} collection."

  @impl true
  def render(assigns) do
    ~H"""
    <BerrypodWeb.PageRenderer.render_page {assigns} />
    """
  end
end
