import { FSDB_COLLECTION } from '@andyburke/fsdb';
import { FSDB_INDEXER_SYMLINKS } from '@andyburke/fsdb/indexers';
import { by_character, by_lurid } from '@andyburke/fsdb/organizers';

export type INVITE_CODE = {
	id: string;
	creator_id: string;
	code: string;
	timestamps: {
		created: string;
		expires: string;
		cancelled?: string;
	};
};

export const INVITE_CODES = new FSDB_COLLECTION<INVITE_CODE>({
	name: 'invite_codes',
	indexers: {
		code: new FSDB_INDEXER_SYMLINKS<INVITE_CODE>({
			name: 'code',
			field: 'code',
			organize: by_character
		}),
		creator_id: new FSDB_INDEXER_SYMLINKS<INVITE_CODE>({
			name: 'creator_id',
			field: 'creator_id',
			to_many: true,
			organize: by_lurid
		})
	}
});

const MAX_INVITE_EXPIRE_TIME = 28 * 24 * 60 * 60 * 1_000;
export function VALIDATE_INVITE_CODE(invite_code: INVITE_CODE) {
	const errors: any[] = [];

	if (typeof invite_code.id !== 'string' || invite_code.id.length !== 49) {
		errors.push({
			cause: 'invalid_invite_code_id',
			message: 'An invite code must have a lurid id, eg: able-fish-gold-wing-trip-form-seed-cost-rope-wife'
		});
	}

	if (typeof invite_code.code !== 'string' || invite_code.id.length < 3) {
		errors.push({
			cause: 'invalid_invite_code_code',
			message: 'An invite code must have a secret code that is at least 3 characters long.'
		});
	}

	if (typeof invite_code.timestamps?.expires !== 'string') {
		errors.push({
			cause: 'missing_invite_expiration',
			message: 'Invite codes must have an expiration set.'
		});
	}

	const expiration_delta = new Date(invite_code.timestamps.expires).valueOf() - new Date(invite_code.timestamps.created).valueOf();
	if (expiration_delta > MAX_INVITE_EXPIRE_TIME || expiration_delta < 0) {
		errors.push({
			cause: 'invite_expiration_invalid',
			message: 'Invite codes must expire within a limited window after they are created.'
		});
	}

	return errors.length ? errors : undefined;
}
