defmodule Tarakan.Billing.Notifier do
  @moduledoc """
  Text-only billing/alert emails, modelled on
  `Tarakan.Accounts.AccountNotifier`.
  """

  import Swoosh.Email

  alias Tarakan.Mailer

  defp deliver(recipient, subject, body) do
    email =
      new()
      |> to(recipient)
      |> from({"Tarakan Security", "security@tarakan.lol"})
      |> subject(subject)
      |> text_body(body)

    with {:ok, _metadata} <- Mailer.deliver(email) do
      {:ok, email}
    end
  end

  @doc """
  Delivers a watchlist alert digest. `findings` are maps with `:repository`
  (`{host, owner, name}`), `:title`, `:severity`, and `:public_id`.
  `regressions` carry the same keys plus `:fixed_at` and
  `:detected_commit_sha`, and are listed first: a bug that came back is more
  urgent than one that is merely new.
  """
  def deliver_watchlist_alert(account, watchlist, findings, regressions \\ []) do
    count = length(findings)
    regression_count = length(regressions)

    deliver(
      account.email,
      alert_subject(count, regression_count),
      """

      ==============================

      Tarakan account @#{account.handle},

      Watchlist "#{watchlist.name}" since the last alert:
      #{regression_section(regressions)}#{finding_section(findings)}
      Manage watchlists and alerts at #{TarakanWeb.Endpoint.url()}/alerts

      ==============================
      """
    )
  end

  defp alert_subject(_count, regression_count) when regression_count > 0 do
    "Tarakan alert: #{regression_count} fixed findings came back"
  end

  defp alert_subject(count, _regression_count) do
    "Tarakan alert: #{count} findings across your watchlist"
  end

  defp regression_section([]), do: ""

  defp regression_section(regressions) do
    lines =
      Enum.map_join(regressions, "\n", fn regression ->
        {host, owner, name} = regression.repository
        url = TarakanWeb.Endpoint.url() <> "/findings/#{regression.public_id}"
        fixed_on = if regression.fixed_at, do: Date.to_iso8601(regression.fixed_at), else: "?"
        sha = String.slice(regression.detected_commit_sha || "", 0, 7)

        "- [#{regression.severity}] #{regression.title} (#{host}/#{owner}/#{name})\n" <>
          "  fixed #{fixed_on}, seen again at #{sha}\n  #{url}"
      end)

    """

    REGRESSED - #{length(regressions)} previously fixed finding(s) are back:

    #{lines}
    """
  end

  defp finding_section([]), do: ""

  defp finding_section(findings) do
    lines =
      Enum.map_join(findings, "\n", fn finding ->
        {host, owner, name} = finding.repository
        url = TarakanWeb.Endpoint.url() <> "/findings/#{finding.public_id}"

        "- [#{finding.severity}] #{finding.title} (#{host}/#{owner}/#{name})\n  #{url}"
      end)

    """

    #{length(findings)} new verified or fixed finding(s):

    #{lines}
    """
  end
end
