// Unit tests for `decodeAccountView` — F8-04b adds an `entitlement`
// projection on the TS Account, sourced from the FBS
// `EntitlementSnapshot.is_paid` field. The decode must default to
// `false` when the snapshot is absent, never throw on null.

import { Builder, ByteBuffer } from "flatbuffers";
import { describe, expect, test } from "vitest";

import { decodeAccountView } from "../src/api/account";
import {
	AccountView,
	EntitlementSnapshot,
} from "../src/proto/galaxy/fbs/user";

function buildAccountView(opts: {
	isPaid?: boolean;
	includeEntitlement: boolean;
}): AccountView {
	const builder = new Builder(256);
	const userIdOff = builder.createString("user-1");
	const emailOff = builder.createString("user@example.com");
	const userNameOff = builder.createString("Player-1");
	const displayNameOff = builder.createString("Display");
	const langOff = builder.createString("en-US");
	const tzOff = builder.createString("UTC");
	const countryOff = builder.createString("US");

	let entitlementOff = 0;
	if (opts.includeEntitlement) {
		const planOff = builder.createString("free");
		const sourceOff = builder.createString("default");
		const reasonOff = builder.createString("init");
		EntitlementSnapshot.startEntitlementSnapshot(builder);
		EntitlementSnapshot.addPlanCode(builder, planOff);
		EntitlementSnapshot.addIsPaid(builder, opts.isPaid ?? false);
		EntitlementSnapshot.addSource(builder, sourceOff);
		EntitlementSnapshot.addReasonCode(builder, reasonOff);
		entitlementOff = EntitlementSnapshot.endEntitlementSnapshot(builder);
	}

	AccountView.startAccountView(builder);
	AccountView.addUserId(builder, userIdOff);
	AccountView.addEmail(builder, emailOff);
	AccountView.addUserName(builder, userNameOff);
	AccountView.addDisplayName(builder, displayNameOff);
	AccountView.addPreferredLanguage(builder, langOff);
	AccountView.addTimeZone(builder, tzOff);
	AccountView.addDeclaredCountry(builder, countryOff);
	if (entitlementOff !== 0) {
		AccountView.addEntitlement(builder, entitlementOff);
	}
	const viewOff = AccountView.endAccountView(builder);
	builder.finish(viewOff);

	return AccountView.getRootAsAccountView(new ByteBuffer(builder.asUint8Array()));
}

describe("decodeAccountView", () => {
	test("extracts entitlement.isPaid=true from FBS EntitlementSnapshot", () => {
		const view = buildAccountView({ includeEntitlement: true, isPaid: true });
		const account = decodeAccountView(view);
		expect(account.entitlement.isPaid).toBe(true);
	});

	test("extracts entitlement.isPaid=false from FBS EntitlementSnapshot", () => {
		const view = buildAccountView({ includeEntitlement: true, isPaid: false });
		const account = decodeAccountView(view);
		expect(account.entitlement.isPaid).toBe(false);
	});

	test("defaults entitlement.isPaid to false when snapshot is absent", () => {
		const view = buildAccountView({ includeEntitlement: false });
		const account = decodeAccountView(view);
		expect(account.entitlement.isPaid).toBe(false);
	});

	test("populates other Account fields verbatim", () => {
		const view = buildAccountView({ includeEntitlement: true, isPaid: true });
		const account = decodeAccountView(view);
		expect(account.userId).toBe("user-1");
		expect(account.email).toBe("user@example.com");
		expect(account.userName).toBe("Player-1");
		expect(account.displayName).toBe("Display");
		expect(account.preferredLanguage).toBe("en-US");
		expect(account.timeZone).toBe("UTC");
		expect(account.declaredCountry).toBe("US");
	});
});
