defmodule BerrypodWeb.Shop.Pages.Collection do
  @moduledoc """
  Collection page handler for the unified Shop.Page LiveView.
  """

  import Phoenix.Component, only: [assign: 3]
  import Phoenix.LiveView, only: [push_patch: 2, push_navigate: 2, put_flash: 3]

  alias Berrypod.{Pages, Pagination, Products}
  alias BerrypodWeb.R

  @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"}
  ]

  def init(socket, _params, _uri) do
    page = Pages.get_page("collection")

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

    {:noreply, socket}
  end

  # When accessed via custom URL (e.g. /shop) without a collection slug, show all products
  def handle_params(params, uri, socket) when not is_map_key(params, "slug") do
    handle_params(Map.put(params, "slug", "all"), uri, socket)
  end

  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} ->
        socket =
          socket
          |> assign(:page_title, title)
          |> assign(:page_description, collection_description(title))
          |> assign(:og_url, R.url(R.collection(slug)))
          |> assign(:collection_title, title)
          |> assign(:collection_slug, slug)
          |> assign(:current_category, category)
          |> assign(:current_sort, sort)
          |> assign(:pagination, pagination)
          |> assign(:products, pagination.items)

        {:noreply, socket}

      :not_found ->
        socket =
          socket
          |> put_flash(:error, "Collection not found")
          |> push_navigate(to: R.collection("all"))

        {:noreply, socket}
    end
  end

  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: R.collection(slug) <> "?sort=#{sort}")}
  end

  def handle_event(_event, _params, _socket), do: :cont

  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

  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."
end
