defmodule WhoNeedHelp.GoogleAuthTest do
  use ExUnit.Case, async: true

  alias WhoNeedHelp.GoogleAuth.AssentAdapter

  test "Google authorization uses OIDC state, nonce, PKCE, and identity-only scopes" do
    nonce = "session-bound-nonce"

    assert {:ok, %{url: url, session_params: session_params}} =
             Assent.Strategy.Google.authorize_url(
               client_id: "client",
               client_secret: "secret",
               redirect_uri: "https://example.test/auth/google/callback",
               nonce: nonce,
               code_verifier: true,
               openid_configuration: %{
                 "authorization_endpoint" => "https://accounts.google.test/o/oauth2/v2/auth"
               }
             )

    uri = URI.parse(url)
    params = URI.decode_query(uri.query)

    assert uri.host == "accounts.google.test"
    assert params["redirect_uri"] == "https://example.test/auth/google/callback"
    assert params["scope"] == "openid email profile"
    assert params["state"] == session_params.state
    assert params["nonce"] == nonce
    assert session_params.nonce == nonce
    assert params["code_challenge_method"] == "S256"
    assert is_binary(session_params.code_verifier)
    refute Map.has_key?(params, "access_type")
  end

  test "normalizes only a verified Google identity and discards token-shaped claims" do
    assert {:ok, identity} =
             AssentAdapter.normalize_identity(%{
               "sub" => "google-subject-123",
               "email" => " Alice@Example.COM ",
               "email_verified" => true,
               "name" => "Alice Neighbor",
               "access_token" => "must-not-leak",
               "id_token" => "must-not-leak"
             })

    assert identity == %{
             provider_uid: "google-subject-123",
             email: "alice@example.com",
             email_verified: true,
             display_name: "Alice Neighbor"
           }

    refute Map.has_key?(identity, :access_token)
    refute Map.has_key?(identity, :id_token)
  end

  test "rejects an unverified or incomplete Google email" do
    assert {:error, :email_not_verified} =
             AssentAdapter.normalize_identity(%{
               "sub" => "subject",
               "email" => "alice@example.com",
               "email_verified" => false
             })

    assert {:error, :invalid_provider_identity} =
             AssentAdapter.normalize_identity(%{
               "sub" => "subject",
               "email_verified" => true
             })
  end
end
