defmodule BerrypodWeb.NewsletterController do
  use BerrypodWeb, :controller

  alias Berrypod.Newsletter

  plug BerrypodWeb.Plugs.RateLimit, [type: :newsletter] when action == :subscribe

  @doc "No-JS fallback for newsletter signup form."
  def subscribe(conn, %{"email" => email}) do
    ip_hash = hash_ip(conn)

    case Newsletter.subscribe(email,
           consent_text: "Newsletter signup on website",
           ip_hash: ip_hash
         ) do
      {:ok, _} ->
        conn
        |> put_flash(:info, "Check your inbox to confirm your subscription.")
        |> redirect(to: redirect_back(conn))

      {:already_confirmed, _} ->
        conn
        |> put_flash(:info, "You're already subscribed!")
        |> redirect(to: redirect_back(conn))

      {:error, _} ->
        conn
        |> put_flash(:error, "Please enter a valid email address.")
        |> redirect(to: redirect_back(conn))
    end
  end

  def subscribe(conn, _params) do
    conn
    |> put_flash(:error, "Please enter your email address.")
    |> redirect(to: ~p"/")
  end

  @doc "Handles confirmation link from the double opt-in email."
  def confirm(conn, %{"token" => token}) do
    case Newsletter.confirm(token) do
      {:ok, _sub} ->
        conn
        |> put_status(200)
        |> html(confirmation_html(:success))

      {:error, :invalid_token} ->
        conn
        |> put_status(400)
        |> html(confirmation_html(:invalid))
    end
  end

  defp confirmation_html(:success) do
    shop_name = Berrypod.Settings.get_setting("shop_name", "Berrypod")

    """
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Subscription confirmed</title>
      <style>body{font-family:system-ui,sans-serif;max-width:480px;margin:80px auto;padding:0 24px;color:#111}</style>
    </head>
    <body>
      <h1 style="font-size:1.25rem;margin-bottom:0.75rem">You're subscribed!</h1>
      <p style="color:#555">Thanks for confirming. You'll receive the #{shop_name} newsletter from now on.</p>
      <p style="margin-top:1.5rem"><a href="/" style="color:#111">Back to the shop</a></p>
    </body>
    </html>
    """
  end

  defp confirmation_html(:invalid) do
    """
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Invalid link</title>
      <style>body{font-family:system-ui,sans-serif;max-width:480px;margin:80px auto;padding:0 24px;color:#111}</style>
    </head>
    <body>
      <h1 style="font-size:1.25rem;margin-bottom:0.75rem">Link invalid or expired</h1>
      <p style="color:#555">This confirmation link has expired or is invalid. Please try subscribing again.</p>
      <p style="margin-top:1.5rem"><a href="/" style="color:#111">Back to the shop</a></p>
    </body>
    </html>
    """
  end

  defp redirect_back(conn) do
    case get_req_header(conn, "referer") do
      [referer | _] ->
        uri = URI.parse(referer)
        uri.path || "/"

      _ ->
        "/"
    end
  end

  defp hash_ip(conn) do
    daily_salt = Date.utc_today() |> Date.to_iso8601()
    ip_string = conn.remote_ip |> :inet.ntoa() |> to_string()
    :crypto.hash(:sha256, ip_string <> daily_salt) |> Base.encode16(case: :lower)
  end
end
