defmodule Berrypod.Reviews.ReviewNotifier do
  @moduledoc """
  Sends transactional emails for the review system.

  Verification emails for review submission, and review request emails
  after order delivery.
  """

  import Swoosh.Email

  alias Berrypod.Mailer

  require Logger

  @doc """
  Sends a verification email with a link to leave a review.

  The link contains a signed token encoding the email and product_id.
  """
  def deliver_review_verification(email, product_title, link) do
    subject = "Leave a review for #{product_title}"

    body = """
    ==============================

    Thanks for your purchase!

    Click here to leave a review for #{product_title}:

    #{link}

    This link expires in 1 hour.

    If you didn't request this, you can ignore this email.

    ==============================
    """

    deliver(email, subject, body)
  end

  @doc """
  Sends a review request email after order delivery.

  Includes links to review each product in the order that hasn't been
  reviewed yet. Each link contains a signed token for that email+product.
  """
  def deliver_review_request(order, unreviewable_products) do
    shop_name = Berrypod.Settings.get_setting("shop_name", "Berrypod")
    customer_name = extract_customer_name(order)

    product_links =
      unreviewable_products
      |> Enum.map(fn %{product_id: product_id, product_name: name} ->
        token = Berrypod.Reviews.generate_review_token(order.customer_email, product_id)
        link = BerrypodWeb.Endpoint.url() <> "/reviews/new?token=#{token}"
        "  #{name}\n  #{link}"
      end)
      |> Enum.join("\n\n")

    body = """
    ==============================

    Hi#{if customer_name, do: " #{customer_name}", else: ""},

    Your order #{order.order_number} was delivered recently. We'd love to hear what you think!

    #{product_links}

    Thanks for shopping with us.

    ==============================
    """

    deliver(
      order.customer_email,
      "How was your order from #{shop_name}?",
      body
    )
  end

  defp extract_customer_name(%{shipping_address: %{"name" => name}}) when is_binary(name) do
    name |> String.split(" ") |> List.first()
  end

  defp extract_customer_name(_), do: nil

  # --- Private ---

  defp deliver(recipient, subject, body) do
    shop_name = Berrypod.Settings.get_setting("shop_name", "Berrypod")
    from_address = Berrypod.Settings.get_setting("email_from_address", "contact@example.com")

    email =
      new()
      |> to(recipient)
      |> from({shop_name, from_address})
      |> subject(subject)
      |> text_body(body)

    case Mailer.deliver(email) do
      {:ok, _metadata} = result ->
        result

      {:error, reason} = error ->
        Logger.warning("Failed to send review email to #{recipient}: #{inspect(reason)}")
        error
    end
  end
end
