import { describe, expect, test } from "bun:test";

// ---------------------------------------------------------------------------
// Slice 1: buildSocialProviders — conditional provider registration
//
// Public interface under test: buildSocialProviders(env) → object
// Behaviour: only registers providers whose env vars are all present.
// ---------------------------------------------------------------------------

import { buildSocialProviders } from "@/lib/build-social-providers";

describe("buildSocialProviders", () => {
	test("returns empty object when no OAuth env vars are set", () => {
		const result = buildSocialProviders({});
		expect(result).toEqual({});
	});

	test("registers google when both Google vars are present", () => {
		const result = buildSocialProviders({
			AUTH_GOOGLE_CLIENT_ID: "gid",
			AUTH_GOOGLE_CLIENT_SECRET: "gsecret",
		});
		expect(result).toHaveProperty("google");
		expect(result.google).toMatchObject({
			clientId: "gid",
			clientSecret: "gsecret",
		});
	});

	test("does NOT register google when only clientId is present", () => {
		const result = buildSocialProviders({
			AUTH_GOOGLE_CLIENT_ID: "gid",
		});
		expect(result).not.toHaveProperty("google");
	});

	test("does NOT register google when only clientSecret is present", () => {
		const result = buildSocialProviders({
			AUTH_GOOGLE_CLIENT_SECRET: "gsecret",
		});
		expect(result).not.toHaveProperty("google");
	});

	test("registers apple when all four Apple vars are present", () => {
		const result = buildSocialProviders({
			AUTH_APPLE_CLIENT_ID: "aid",
			AUTH_APPLE_CLIENT_SECRET: "asecret",
			AUTH_APPLE_TEAM_ID: "TEAM1",
			AUTH_APPLE_KEY_ID: "KEY1",
			AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----",
		});
		expect(result).toHaveProperty("apple");
		expect(result.apple).toMatchObject({
			clientId: "aid",
			clientSecret: "asecret",
		});
	});

	test("does NOT register apple when any Apple var is missing", () => {
		const result = buildSocialProviders({
			AUTH_APPLE_CLIENT_ID: "aid",
			AUTH_APPLE_CLIENT_SECRET: "asecret",
			AUTH_APPLE_TEAM_ID: "TEAM1",
			// AUTH_APPLE_KEY_ID missing
			AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----",
		});
		expect(result).not.toHaveProperty("apple");
	});

	test("registers both google and apple when all vars are present", () => {
		const result = buildSocialProviders({
			AUTH_GOOGLE_CLIENT_ID: "gid",
			AUTH_GOOGLE_CLIENT_SECRET: "gsecret",
			AUTH_APPLE_CLIENT_ID: "aid",
			AUTH_APPLE_CLIENT_SECRET: "asecret",
			AUTH_APPLE_TEAM_ID: "TEAM1",
			AUTH_APPLE_KEY_ID: "KEY1",
			AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----",
		});
		expect(result).toHaveProperty("google");
		expect(result).toHaveProperty("apple");
	});
});

// ---------------------------------------------------------------------------
// Slice 2: auth-client — signIn.social is available
//
// Public interface under test: authClient.signIn.social
// Behaviour: the function exists and is callable (no plugin wiring needed
// for socialProviders on the client — it's built into createAuthClient).
// ---------------------------------------------------------------------------

import { authClient } from "@/lib/auth-client";

describe("authClient", () => {
	test("exposes signIn.social as a function", () => {
		expect(typeof authClient.signIn.social).toBe("function");
	});

	test("exposes useSession hook", () => {
		expect(typeof authClient.useSession).toBe("function");
	});
});

// ---------------------------------------------------------------------------
// Slice 3: getSignInProviders — sign-in page provider list
//
// Public interface under test: getSignInProviders()
// Behaviour: returns the ordered list of available sign-in providers with
// their labels and ids, based on which env vars are configured.
// The component consumes this list to render buttons — testing the list
// verifies the button-to-provider mapping without needing a DOM.
// ---------------------------------------------------------------------------

import { getSignInProviders } from "@/lib/get-sign-in-providers";

describe("getSignInProviders", () => {
	test("returns authentik when Authentik vars are set", () => {
		const providers = getSignInProviders({
			AUTH_AUTHENTIK_CLIENT_ID: "id",
			AUTH_AUTHENTIK_CLIENT_SECRET: "secret",
			AUTH_AUTHENTIK_ISSUER: "https://auth.example.com",
		});
		const ids = providers.map((p) => p.id);
		expect(ids).toContain("authentik");
	});

	test("returns google when Google vars are set", () => {
		const providers = getSignInProviders({
			AUTH_GOOGLE_CLIENT_ID: "gid",
			AUTH_GOOGLE_CLIENT_SECRET: "gsecret",
		});
		const ids = providers.map((p) => p.id);
		expect(ids).toContain("google");
	});

	test("returns apple when Apple vars are set", () => {
		const providers = getSignInProviders({
			AUTH_APPLE_CLIENT_ID: "aid",
			AUTH_APPLE_CLIENT_SECRET: "asecret",
			AUTH_APPLE_TEAM_ID: "TEAM1",
			AUTH_APPLE_KEY_ID: "KEY1",
			AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----",
		});
		const ids = providers.map((p) => p.id);
		expect(ids).toContain("apple");
	});

	test("returns empty list when no vars are set", () => {
		const providers = getSignInProviders({});
		expect(providers).toHaveLength(0);
	});

	test("each provider has id, label, and signInMethod", () => {
		const providers = getSignInProviders({
			AUTH_GOOGLE_CLIENT_ID: "gid",
			AUTH_GOOGLE_CLIENT_SECRET: "gsecret",
		});
		expect(providers[0]).toMatchObject({
			id: expect.any(String),
			label: expect.any(String),
			signInMethod: expect.any(String),
		});
	});

	test("google provider uses 'social' signInMethod", () => {
		const providers = getSignInProviders({
			AUTH_GOOGLE_CLIENT_ID: "gid",
			AUTH_GOOGLE_CLIENT_SECRET: "gsecret",
		});
		const google = providers.find((p) => p.id === "google");
		expect(google?.signInMethod).toBe("social");
	});

	test("apple provider uses 'social' signInMethod", () => {
		const providers = getSignInProviders({
			AUTH_APPLE_CLIENT_ID: "aid",
			AUTH_APPLE_CLIENT_SECRET: "asecret",
			AUTH_APPLE_TEAM_ID: "TEAM1",
			AUTH_APPLE_KEY_ID: "KEY1",
			AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----",
		});
		const apple = providers.find((p) => p.id === "apple");
		expect(apple?.signInMethod).toBe("social");
	});

	test("authentik provider uses 'oauth2' signInMethod", () => {
		const providers = getSignInProviders({
			AUTH_AUTHENTIK_CLIENT_ID: "id",
			AUTH_AUTHENTIK_CLIENT_SECRET: "secret",
			AUTH_AUTHENTIK_ISSUER: "https://auth.example.com",
		});
		const authentik = providers.find((p) => p.id === "authentik");
		expect(authentik?.signInMethod).toBe("oauth2");
	});
});
