/*
Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Backend
Copyright (C) 2024 Christian Fraß

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public 
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later 
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see 
<https://www.gnu.org/licenses/>. 
 */

namespace _espe.service.invite
{
	
	/**
	 */
	export async function create(
		{
			"membership_number_mode": membership_number_mode,
			"membership_number_value": membership_number_value,
			"name_mode": name_mode,
			"name_value": name_value,
			"email_address_mode": email_address_mode,
			"email_address_value": email_address_value,
			"groups_mode": groups_mode,
			"groups_value": groups_value,
		} : {
			membership_number_mode : _espe.type.invite_prefill_mode;
			membership_number_value : (null | string);
			name_mode : _espe.type.invite_prefill_mode;
			name_value : string;
			email_address_mode : _espe.type.invite_prefill_mode;
			email_address_value : (null | string);
			groups_mode : _espe.type.invite_prefill_mode;
			groups_value : Array<string>;
		},
		{
			"expiry": expiry = -1,
		} : {
			expiry ?: (null | int);
		} = {
		}
	) : Promise<{id : _espe.type.invite_id; key : _espe.type.invite_key}>
	{
		/**
		 * @todo outsource to conf
		 */
		const default_lifetime : int = (60 * 60 * 24 * 7 * 2);
		/**
		 * @todo proper salt
		 */
		const invite_key : _espe.type.invite_key = lib_plankton.sha256.get(
			(
				name_value
				+
				"/"
				+
				lib_plankton.base.get_current_timestamp(true).toFixed(0)
			),
			"secret"
		);
		const invite_object : _espe.type.invite_object = {
			"key": invite_key,
			"expiry": (
				((expiry !== null) && (expiry < 0))
				?
				(lib_plankton.base.get_current_timestamp(true) + default_lifetime)
				:
				expiry
			),
			"membership_number_mode": membership_number_mode,
			"membership_number_value": membership_number_value,
			"name_mode": name_mode,
			"name_value": name_value,
			"email_address_mode": email_address_mode,
			"email_address_value": email_address_value,
			"groups_mode": groups_mode,
			"groups_value": groups_value,
		};
		const invite_id : _espe.type.invite_id = await _espe.repository.invite.create(invite_object);
		return {
			"id": invite_id,
			"key": invite_key,
		};
	}
	
	
	/**
	 */
	function get(
		key : _espe.type.invite_key
	) : Promise<_espe.type.invite_object>
	{
		return (
			_espe.repository.invite.identify(key)
			.then(
				(id) => _espe.repository.invite.read(id)
			)
		);
	}
	
	
	/**
	 */
	export async function examine(
		key : _espe.type.invite_key
	) : Promise<_espe.type.invite_object>
	{
		let invite_object : (null | _espe.type.invite_object);
		try {
			invite_object = await get(key);
		}
		catch (error) {
			invite_object = null;
		}
		if (invite_object === null) {
			return Promise.reject(new Error("not found"))
		}
		else {
			const now : int = lib_plankton.base.get_current_timestamp(true);
			if ((invite_object.expiry !== null) && (invite_object.expiry < now)) {
				return Promise.reject(new Error("expired"));
			}
			else {
				return Promise.resolve(invite_object);
			}
		}
	}
	
	
	/**
	 * @todo heed expiry
	 * @todo password?
	 */
	export async function accept(
		key : _espe.type.invite_key,
		membership_number_value : (null | string),
		name_value : (null | string),
		email_address_value : (null | string),
		groups_value : Array<string>
	) : Promise<void>
	{
		const invite_id : _espe.type.invite_id = await _espe.repository.invite.identify(key);
		const invite_object : _espe.type.invite_object = await _espe.repository.invite.read(invite_id);
		const now : int = lib_plankton.base.get_current_timestamp(true);
		if ((invite_object.expiry !== null) && (invite_object.expiry < now)) {
			return Promise.reject(new Error("expired"));
		}
		else {
			const member_id : _espe.type.member_id = await _espe.service.member.project(
				{
					"membership_number": (
						(invite_object.membership_number_mode === _espe.type.invite_prefill_mode.free)
						?
						membership_number_value
						:
						invite_object.membership_number_value
					),
					"name_real_value": (
						(
							(invite_object.name_mode === _espe.type.invite_prefill_mode.free)
							&&
							(name_value !== null)
						)
						?
						name_value
						:
						invite_object.name_value
					),
					"email_address_private": (
						(
							(invite_object.email_address_mode === _espe.type.invite_prefill_mode.free)
							&&
							(email_address_value !== null)
						)
						?
						email_address_value
						:
						invite_object.email_address_value
					),
					"groups": (
						(invite_object.groups_mode === _espe.type.invite_prefill_mode.free)
						?
						groups_value
						:
						invite_object.groups_value
					),
				}
			);
			await _espe.repository.invite.delete_(invite_id);
		}
	}
	
}
