defmodule TarakanWeb.BadgeControllerTest do
  use TarakanWeb.ConnCase, async: true

  alias Tarakan.Repo
  alias Tarakan.Scans.CanonicalFinding

  defp fixed_finding_fixture(repository, days_to_fix) do
    now = DateTime.utc_now()

    %CanonicalFinding{}
    |> Ecto.Changeset.change(%{
      repository_id: repository.id,
      fingerprint: "fp-#{System.unique_integer([:positive])}",
      file_path: "lib/app.ex",
      line_start: 1,
      severity: "high",
      title: "Finding",
      description: "Body.",
      status: "fixed",
      first_seen_commit_sha: random_commit_sha(),
      last_seen_commit_sha: random_commit_sha(),
      fixed_commit_sha: random_commit_sha(),
      verified_at: DateTime.add(now, -days_to_fix * 86_400, :second),
      fixed_at: now,
      inserted_at: now,
      updated_at: now
    })
    |> Repo.insert!()
  end

  test "serves an SVG carrying the median fix time", %{conn: conn} do
    repository = listed_github_repository_fixture()
    fixed_finding_fixture(repository, 3)

    conn = get(conn, ~p"/badges/github.com/#{repository.owner}/#{repository.name}")

    assert response_content_type(conn, :svg) =~ "image/svg+xml"
    body = response(conn, 200)

    assert body =~ "<svg"
    assert body =~ "security"
    assert body =~ "3d median fix"
    assert get_resp_header(conn, "cache-control") == ["public, max-age=900"]
  end

  test "resolves a hosted repository from its bare slug", %{conn: conn} do
    repository = listed_hosted_repository_fixture()

    conn = get(conn, ~p"/badges/#{repository.owner}/#{repository.name}")

    assert response(conn, 200) =~ "no findings"
  end

  test "does not leak whether an unlisted repository exists", %{conn: conn} do
    repository =
      github_repository_fixture()
      |> Tarakan.Repositories.Repository.listing_changeset(%{listing_status: "quarantined"})
      |> Repo.update!()

    quarantined =
      get(conn, ~p"/badges/github.com/#{repository.owner}/#{repository.name}")
      |> response(200)

    missing =
      get(conn, ~p"/badges/github.com/nobody/nothing")
      |> response(200)

    assert quarantined =~ "not listed"
    assert quarantined == missing
  end
end
