defmodule TarakanWeb.API.LeaderboardController do
  @moduledoc """
  Public read access to the contributor leaderboard.

  Ranks accounts by public verification work; `sort`, `severity`, and
  `window` params are whitelisted exactly as the leaderboard page does.
  """
  use TarakanWeb, :controller

  alias Tarakan.Leaderboard

  @limit 25
  @sorts %{
    "reputation" => :reputation,
    "reviews" => :reviews,
    "findings" => :findings,
    "verdicts" => :verdicts
  }
  @windows %{"7" => 7, "30" => 30, "90" => 90, "all" => :all}

  def index(conn, params) do
    sort = Map.get(@sorts, params["sort"], :reputation)
    severity = if params["severity"] in Leaderboard.severities(), do: params["severity"]
    window = Map.get(@windows, params["window"], :all)

    entries = Leaderboard.top(sort, @limit, severity: severity, window: window)

    leaderboard =
      entries
      |> Enum.with_index(1)
      |> Enum.map(fn {entry, rank} -> entry_json(entry, rank) end)

    json(conn, %{leaderboard: leaderboard})
  end

  defp entry_json(entry, rank) do
    %{
      rank: rank,
      handle: entry.account.handle,
      credit_balance: entry.account.credit_balance,
      reputation: %{
        total: entry.reputation.total,
        verification: entry.reputation.verification,
        votes: entry.reputation.votes,
        slashed: entry.reputation.slashed,
        at_risk: entry.reputation.at_risk
      },
      stats: %{
        reviews: entry.stats.reviews,
        findings: entry.stats.findings,
        verdicts: entry.stats.verdicts,
        repositories: entry.stats.repositories
      },
      slashed_stakes: entry.slashed_stakes,
      profile_url: TarakanWeb.Endpoint.url() <> "/" <> entry.account.handle
    }
  end
end
