defmodule BerrypodWeb.Plugs.Redirects do
  @moduledoc """
  Plug that handles URL normalisation and custom redirects.

  Three concerns in one pass:
  1. Trailing slash removal (/products/foo/ → /products/foo)
  2. Case normalisation for shop paths (/Products/Foo → /products/foo)
  3. Custom redirect lookup from the redirects table (ETS-cached)

  All redirects preserve query params.
  """

  import Plug.Conn
  alias Berrypod.Redirects

  # Only case-normalise paths under these prefixes (SEO-relevant shop routes).
  # Paths with tokens, API keys, or other case-sensitive segments are excluded.
  @lowercase_prefixes ~w(/products /collections /about /delivery /privacy /terms /search /cart /contact)

  def init(opts), do: opts

  def call(conn, _opts) do
    path = conn.request_path
    stripped = strip_trailing_slash(path)

    cond do
      # Trailing slash — redirect to canonical form
      stripped != path ->
        redirect_to(conn, stripped, 301)

      # Case mismatch on a shop path — redirect to lowercase
      lowercase_path?(path) and String.downcase(path) != path ->
        redirect_to(conn, String.downcase(path), 301)

      # Check redirect table (ETS-cached)
      :else ->
        case Redirects.lookup(path) do
          {:ok, redirect} ->
            Redirects.increment_hit_count(redirect)
            redirect_to(conn, redirect.to_path, redirect.status_code)

          :not_found ->
            conn
        end
    end
  end

  defp lowercase_path?(path) do
    Enum.any?(@lowercase_prefixes, &String.starts_with?(String.downcase(path), &1))
  end

  defp redirect_to(conn, target, status_code) do
    location = append_query(target, conn.query_string)

    conn
    |> put_resp_header("location", location)
    |> send_resp(status_code, "")
    |> halt()
  end

  defp strip_trailing_slash("/"), do: "/"
  defp strip_trailing_slash(path), do: String.trim_trailing(path, "/")

  defp append_query(path, ""), do: path
  defp append_query(path, qs), do: "#{path}?#{qs}"
end
