defmodule BerrypodWeb.ShopComponents.Cart do
  @moduledoc false

  use Phoenix.Component

  import BerrypodWeb.ShopComponents.Base

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

  defp close_cart_drawer_js do
    Phoenix.LiveView.JS.push("close_cart_drawer")
  end

  @doc """
  Renders the cart drawer (floating sidebar).

  The drawer slides in from the right when opened. It displays cart items
  and checkout options. Follows WAI-ARIA dialog pattern for accessibility.

  ## Attributes

  * `cart_items` - List of cart items to display. Each item should have
    `image`, `name`, `variant`, `price`, and `variant_id` keys. Default: []
  * `subtotal` - The subtotal to display. Default: nil (shows "£0.00")
  * `cart_count` - Number of items for screen reader description. Default: 0
  * `mode` - Either `:live` (default) for real stores or `:preview` for theme editor.
    In preview mode, "View basket" navigates via LiveView JS commands.

  ## Examples

      <.cart_drawer cart_items={@cart.items} subtotal={@cart.subtotal} />
      <.cart_drawer cart_items={demo_items} subtotal="£72.00" mode={:preview} />
  """

  attr :cart_items, :list, default: []
  attr :subtotal, :string, default: nil
  attr :total, :string, default: nil
  attr :cart_count, :integer, default: 0
  attr :cart_status, :string, default: nil
  attr :mode, :atom, default: :live
  attr :open, :boolean, default: false
  attr :shipping_estimate, :integer, default: nil
  attr :country_code, :string, default: "GB"
  attr :available_countries, :list, default: []
  attr :stripe_connected, :boolean, default: true

  def cart_drawer(assigns) do
    # Check if any cart items are unavailable (out of stock or discontinued)
    has_unavailable_items =
      Enum.any?(assigns.cart_items, fn item ->
        Map.get(item, :product_discontinued) == true or Map.get(item, :is_available) == false
      end)

    assigns =
      assigns
      |> assign_new(:display_total, fn ->
        assigns.total || assigns.subtotal || "£0.00"
      end)
      |> assign(:has_unavailable_items, has_unavailable_items)

    ~H"""
    <%!-- Screen reader announcements for cart changes --%>
    <div aria-live="polite" aria-atomic="true" class="sr-only">
      {@cart_status}
    </div>

    <!-- Cart Drawer Overlay -->
    <div
      id="cart-drawer-overlay"
      class={["cart-drawer-overlay", @open && "open"]}
      aria-hidden={to_string(!@open)}
      phx-click={close_cart_drawer_js()}
    >
    </div>

    <!-- Cart Drawer -->
    <div
      id="cart-drawer"
      role="dialog"
      aria-modal="true"
      aria-labelledby="cart-drawer-title"
      aria-describedby="cart-drawer-description"
      aria-hidden={to_string(!@open)}
      phx-hook="CartDrawer"
      class={["cart-drawer", @open && "open"]}
    >
      <p id="cart-drawer-description" class="sr-only">
        Shopping basket with {@cart_count} {if @cart_count == 1, do: "item", else: "items"}. Press Escape to close.
      </p>
      <div class="cart-drawer-header">
        <h2
          id="cart-drawer-title"
          class="cart-drawer-title"
        >
          Your basket
        </h2>
        <button
          type="button"
          class="cart-drawer-close"
          phx-click={close_cart_drawer_js()}
          aria-label="Close cart"
        >
          <svg
            class="cart-drawer-close-icon"
            width="20"
            height="20"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
          >
            <line x1="18" y1="6" x2="6" y2="18"></line>
            <line x1="6" y1="6" x2="18" y2="18"></line>
          </svg>
        </button>
      </div>

      <div class="cart-drawer-items">
        <%= if @cart_items == [] do %>
          <.cart_empty_state mode={@mode} />
        <% else %>
          <ul role="list" aria-label="Cart items">
            <%= for item <- @cart_items do %>
              <li>
                <.cart_item_row item={item} size={:compact} show_quantity_controls mode={@mode} />
              </li>
            <% end %>
          </ul>
        <% end %>
      </div>

      <div class="cart-drawer-footer">
        <.delivery_line
          shipping_estimate={@shipping_estimate}
          country_code={@country_code}
          available_countries={@available_countries}
          mode={@mode}
        />
        <div class="cart-drawer-total">
          <span>{if @shipping_estimate, do: "Estimated total", else: "Subtotal"}</span>
          <span>{@display_total}</span>
        </div>
        <%= cond do %>
          <% @mode == :preview -> %>
            <button type="button" class="cart-drawer-checkout">
              Checkout
            </button>
          <% !@stripe_connected -> %>
            <button type="button" disabled class="cart-drawer-checkout">
              Checkout
            </button>
            <p class="cart-drawer-notice">Checkout isn't available yet.</p>
          <% @has_unavailable_items -> %>
            <button type="button" disabled class="cart-drawer-checkout">
              Checkout
            </button>
            <p class="cart-drawer-notice">
              Remove unavailable items to checkout.
            </p>
          <% true -> %>
            <form action="/checkout" method="post">
              <input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
              <button type="submit" class="cart-drawer-checkout">
                Checkout
              </button>
            </form>
        <% end %>
      </div>
    </div>
    """
  end

  @doc """
  Shared cart item row component used by both drawer and cart page.

  ## Attributes

  * `item` - Required. Cart item with `name`, `variant`, `price`, `quantity`, `image`, `variant_id`, `product_id`.
  * `size` - Either `:compact` (drawer) or `:default` (cart page). Default: :default
  * `show_quantity_controls` - Show +/- buttons. Default: false
  * `mode` - Either `:live` or `:preview`. Default: :live
  """
  attr :item, :map, required: true
  attr :size, :atom, default: :default
  attr :show_quantity_controls, :boolean, default: false
  attr :mode, :atom, default: :live

  def cart_item_row(assigns) do
    ~H"""
    <div
      class="cart-item-row"
      data-size={if @size == :compact, do: "compact"}
    >
      <%= if @mode != :preview do %>
        <.link
          patch={R.product(@item.product_id)}
          class={["cart-item-image", !@item.image && "cart-item-image--empty"]}
          data-size={if @size == :compact, do: "compact"}
          style={if @item.image, do: "background-image: url('#{@item.image}');"}
          aria-label={"View #{@item.name}"}
        >
        </.link>
      <% else %>
        <div
          class={["cart-item-image", !@item.image && "cart-item-image--empty"]}
          data-size={if @size == :compact, do: "compact"}
          style={if @item.image, do: "background-image: url('#{@item.image}');"}
        >
        </div>
      <% end %>
      <div class="cart-item-details">
        <h3 class="cart-item-name" data-size={if @size == :compact, do: "compact"}>
          <%= if @mode != :preview do %>
            <.link
              patch={R.product(@item.product_id)}
              class="cart-item-name-link"
            >
              {@item.name}
            </.link>
          <% else %>
            <span>{@item.name}</span>
          <% end %>
        </h3>
        <%= if @item.variant do %>
          <p class="cart-item-variant-text">
            {@item.variant}
          </p>
        <% end %>

        <p :if={Map.get(@item, :product_discontinued)} class="cart-item-unavailable">
          This product is no longer available
        </p>
        <p
          :if={!Map.get(@item, :product_discontinued) && Map.get(@item, :is_available) == false}
          class="cart-item-unavailable"
        >
          This option is currently out of stock
        </p>

        <div class="cart-item-actions">
          <%= if @show_quantity_controls do %>
            <form
              action="/cart/update"
              method="post"
              phx-submit="update_quantity_form"
              class="cart-qty-group"
            >
              <input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
              <input type="hidden" name="variant_id" value={@item.variant_id} />
              <button
                type="submit"
                name="quantity"
                value={@item.quantity - 1}
                class="cart-qty-btn"
                aria-label={"Decrease quantity of #{@item.name}"}
              >
                −
              </button>
              <span class="cart-qty-display">
                {@item.quantity}
              </span>
              <button
                type="submit"
                name="quantity"
                value={@item.quantity + 1}
                class="cart-qty-btn"
                aria-label={"Increase quantity of #{@item.name}"}
              >
                +
              </button>
            </form>
          <% else %>
            <span class="cart-qty-text">
              Qty: {@item.quantity}
            </span>
          <% end %>

          <.cart_remove_button variant_id={@item.variant_id} item_name={@item.name} />
        </div>
      </div>

      <div class="cart-item-price-col">
        <p class="cart-item-price" data-size={if @size == :compact, do: "compact"}>
          {Berrypod.Cart.format_price(@item.price * @item.quantity)}
        </p>
      </div>
    </div>
    """
  end

  @doc """
  Cart empty state component.
  """
  attr :mode, :atom, default: :live

  def cart_empty_state(assigns) do
    ~H"""
    <div class="cart-empty">
      <svg
        class="cart-empty-icon"
        width="64"
        height="64"
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.5"
      >
        <path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"></path>
        <line x1="3" y1="6" x2="21" y2="6"></line>
        <path d="M16 10a4 4 0 01-8 0"></path>
      </svg>
      <p>Your basket is empty</p>
      <%= if @mode == :preview do %>
        <button
          type="button"
          phx-click="change_preview_page"
          phx-value-page="collection"
          class="cart-continue-link"
        >
          Continue shopping
        </button>
      <% else %>
        <.link
          patch={R.collection("all")}
          class="cart-continue-link"
        >
          Continue shopping
        </.link>
      <% end %>
    </div>
    """
  end

  @doc """
  Remove button for cart items.
  """
  attr :variant_id, :string, required: true
  attr :item_name, :string, default: "item"

  def cart_remove_button(assigns) do
    ~H"""
    <form action="/cart/remove" method="post" phx-submit="remove_item_form" class="cart-remove-form">
      <input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
      <input type="hidden" name="variant_id" value={@variant_id} />
      <button
        type="submit"
        class="cart-remove-btn"
        aria-label={"Remove #{@item_name} from cart"}
      >
        Remove
      </button>
    </form>
    """
  end

  @doc """
  Renders a cart item row.

  ## Attributes

  * `item` - Required. Map with `product` (containing `image_url`, `name`, `price`), `variant`, and `quantity`.
  * `currency` - Optional. Currency symbol. Defaults to "£".

  ## Examples

      <.cart_item item={item} />
  """
  attr :item, :map, required: true

  def cart_item(assigns) do
    ~H"""
    <.shop_card class="cart-page-item">
      <div class="cart-page-image">
        <img
          src={cart_item_image(@item.product)}
          alt={@item.product.title}
          width="96"
          height="96"
          loading="lazy"
        />
      </div>

      <div class="cart-page-item-info">
        <h3 class="cart-page-item-name">
          {@item.product.title}
        </h3>
        <p class="cart-page-item-variant">
          {@item.variant}
        </p>

        <div class="cart-page-item-actions">
          <div class="cart-qty-group">
            <button class="cart-qty-btn">−</button>
            <span class="cart-qty-display">
              {@item.quantity}
            </span>
            <button class="cart-qty-btn">+</button>
          </div>

          <button class="cart-page-item-remove">
            Remove
          </button>
        </div>
      </div>

      <div class="cart-page-item-price-col">
        <p class="cart-page-item-price">
          {Berrypod.Cart.format_price(@item.product.cheapest_price * @item.quantity)}
        </p>
      </div>
    </.shop_card>
    """
  end

  defp cart_item_image(product) do
    ProductImage.url(Product.primary_image(product), 400)
  end

  # Shared delivery line used by both cart_drawer and order_summary.
  # Shows a country <select> when rates are available, falls back to plain text.
  attr :shipping_estimate, :integer, default: nil
  attr :country_code, :string, default: "GB"
  attr :available_countries, :list, default: []
  attr :mode, :atom, default: :live

  defp delivery_line(assigns) do
    ~H"""
    <div class="delivery-line">
      <span class="delivery-line-label">
        Delivery to
        <%= if @available_countries != [] and @mode != :preview do %>
          <form action="/cart/country" method="post" phx-change="change_country">
            <input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
            <select
              name="country"
              class="delivery-select"
              aria-label="Delivery country"
            >
              <%= for {code, name} <- @available_countries do %>
                <option value={code} selected={code == @country_code}>{name}</option>
              <% end %>
            </select>
            <noscript>
              <button type="submit" class="themed-button delivery-country-submit">Update</button>
            </noscript>
          </form>
        <% else %>
          <span>{Berrypod.Shipping.country_name(@country_code)}</span>
        <% end %>
      </span>
      <%= if @shipping_estimate do %>
        <span>{Berrypod.Cart.format_price(@shipping_estimate)}</span>
      <% else %>
        <span>Calculated at checkout</span>
      <% end %>
    </div>
    """
  end

  @doc """
  Renders the order summary card.

  ## Attributes

  * `subtotal` - Required. Subtotal amount (in pence/cents).
  * `shipping_estimate` - Optional. Shipping estimate in pence.
  * `country_code` - Optional. Current country code. Default "GB".
  * `available_countries` - Optional. List of `{code, name}` tuples.
  * `mode` - Either `:live` (default) or `:preview`.

  ## Examples

      <.order_summary subtotal={3600} />
  """
  attr :subtotal, :integer, required: true
  attr :shipping_estimate, :integer, default: nil
  attr :country_code, :string, default: "GB"
  attr :available_countries, :list, default: []
  attr :mode, :atom, default: :live
  attr :stripe_connected, :boolean, default: true
  attr :has_unavailable_items, :boolean, default: false

  def order_summary(assigns) do
    assigns =
      assign(assigns, :estimated_total, assigns.subtotal + (assigns.shipping_estimate || 0))

    ~H"""
    <.shop_card class="order-summary-card">
      <h2 class="order-summary-heading">
        Order summary
      </h2>

      <div class="order-summary-lines">
        <div class="order-summary-line">
          <span>Subtotal</span>
          <span>
            {Berrypod.Cart.format_price(@subtotal)}
          </span>
        </div>
        <.delivery_line
          shipping_estimate={@shipping_estimate}
          country_code={@country_code}
          available_countries={@available_countries}
          mode={@mode}
        />
        <div class="order-summary-divider">
          <div class="order-summary-total">
            <span>
              {if @shipping_estimate, do: "Estimated total", else: "Subtotal"}
            </span>
            <span>
              {Berrypod.Cart.format_price(@estimated_total)}
            </span>
          </div>
        </div>
      </div>

      <%= cond do %>
        <% @mode == :preview -> %>
          <.shop_button class="order-summary-checkout">
            Checkout
          </.shop_button>
          <.shop_button_outline
            phx-click="change_preview_page"
            phx-value-page="collection"
            class="order-summary-continue"
          >
            Continue shopping
          </.shop_button_outline>
        <% !@stripe_connected -> %>
          <.shop_button disabled class="order-summary-checkout">
            Checkout
          </.shop_button>
          <p class="order-summary-notice">Checkout isn't available yet.</p>
          <.shop_link_outline
            href={R.collection("all")}
            class="order-summary-continue"
          >
            Continue shopping
          </.shop_link_outline>
        <% @has_unavailable_items -> %>
          <.shop_button disabled class="order-summary-checkout">
            Checkout
          </.shop_button>
          <p class="order-summary-notice">Remove unavailable items to checkout.</p>
          <.shop_link_outline
            href={R.collection("all")}
            class="order-summary-continue"
          >
            Continue shopping
          </.shop_link_outline>
        <% true -> %>
          <form action="/checkout" method="post" class="order-summary-checkout-form">
            <input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
            <.shop_button type="submit" class="order-summary-checkout">
              Checkout
            </.shop_button>
          </form>
          <.shop_link_outline
            href={R.collection("all")}
            class="order-summary-continue"
          >
            Continue shopping
          </.shop_link_outline>
      <% end %>
    </.shop_card>
    """
  end

  @doc """
  Renders a cart items list with order summary layout.

  ## Attributes

  * `items` - Required. List of cart items.
  * `subtotal` - Required. Subtotal in pence/cents.
  * `currency` - Optional. Currency symbol. Defaults to "£".
  * `mode` - Either `:live` (default) or `:preview`.

  ## Examples

      <.cart_layout items={@cart_items} subtotal={3600} mode={:preview} />
  """
  attr :items, :list, required: true
  attr :subtotal, :integer, required: true
  attr :mode, :atom, default: :live

  def cart_layout(assigns) do
    ~H"""
    <div class="cart-layout">
      <div class="cart-items-stack">
        <%= for item <- @items do %>
          <.cart_item item={item} />
        <% end %>
      </div>

      <div>
        <.order_summary subtotal={@subtotal} mode={@mode} />
      </div>
    </div>
    """
  end
end
