import { quintOut } from 'svelte/easing';
import { crossfade } from 'svelte/transition';

export const [send, receive] = crossfade({
	duration: (d) => Math.sqrt(d * 200),

	// eslint-disable-next-line no-unused-vars
	fallback(node, params) {
		const style = getComputedStyle(node);
		const transform = style.transform === 'none' ? '' : style.transform;

		return {
			duration: 600,
			easing: quintOut,
			css: (t) => `
                transform: ${transform} scale(${t});
                opacity: ${t}
            `
		};
	}
});

/**
 * Validates an email field
 * @file lib/utils/helpers/input.validation.ts
 * @param {string} email - The email to validate
 */
export const isValidEmail = (email) => {
	const EMAIL_REGEX =
		/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
	return EMAIL_REGEX.test(email.trim());
};
/**
 * Validates a strong password field
 * @file lib/utils/helpers/input.validation.ts
 * @param {string} password - The password to validate
 */
export const isValidPasswordStrong = (password) => {
	const strongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})');

	return strongRegex.test(password.trim());
};
/**
 * Validates a medium password field
 * @file lib/utils/helpers/input.validation.ts
 * @param {string} password - The password to validate
 */
export const isValidPasswordMedium = (password) => {
	const mediumRegex = new RegExp(
		'^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})'
	);

	return mediumRegex.test(password.trim());
};

/**
 * Test whether or not an object is empty.
 * @param {Record<string, string>} obj - The object to test
 * @returns `true` or `false`
 */

export function isEmpty(obj) {
	for (const _i in obj) {
		return false;
	}
	return true;
}

/**
 *
 * @param {string} dateString
 * @returns string
 */
export function toRFC3339(dateString) {
	if (!dateString) dateString = '0001-01-01T00:00:00.000Z';
	const date = new Date(dateString);
	return date.toISOString();
}

/**
 *
 * @param {string} dateString
 * @returns string
 */
export function fromRFC3339(dateString) {
	if (!dateString) dateString = '0001-01-01T00:00:00.000Z';
	const date = new Date(dateString);
	return date.toISOString().split('T')[0];
}

/**
 *
 * @param {App.Locals['user']} user - The user object to format
 */
export function userDatesFromRFC3339(user) {
	if (user.dateofbirth) {
		user.dateofbirth = fromRFC3339(user.dateofbirth);
	}
	if (user.membership) {
		if (user.membership.start_date) {
			user.membership.start_date = fromRFC3339(user.membership.start_date);
		}
		if (user.membership.end_date) {
			user.membership.end_date = fromRFC3339(user.membership.end_date);
		}
	}
	if (user.licence?.issued_date) {
		user.licence.issued_date = fromRFC3339(user.licence.issued_date);
	}
	if (user.licence?.expiration_date) {
		user.licence.expiration_date = fromRFC3339(user.licence.expiration_date);
	}
	if (user.bank_account && user.bank_account.mandate_date_signed) {
		user.bank_account.mandate_date_signed = fromRFC3339(user.bank_account.mandate_date_signed);
	}
}

/**
 * Formats dates in the user object to RFC3339 format
 * @param {App.Locals['user']} user - The user object to format
 */
export function userDatesToRFC3339(user) {
	if (user.dateofbirth) {
		user.dateofbirth = toRFC3339(user.dateofbirth);
	}
	if (user.membership) {
		if (user.membership.start_date) {
			user.membership.start_date = toRFC3339(user.membership.start_date);
		}
		if (user.membership.end_date) {
			user.membership.end_date = toRFC3339(user.membership.end_date);
		}
	}
	if (user.licence?.issued_date) {
		user.licence.issued_date = toRFC3339(user.licence.issued_date);
	}
	if (user.licence?.expiration_date) {
		user.licence.expiration_date = toRFC3339(user.licence.expiration_date);
	}
	if (user.bank_account && user.bank_account.mandate_date_signed) {
		user.bank_account.mandate_date_signed = toRFC3339(user.bank_account.mandate_date_signed);
	}
}

/**
 *
 * @param {string | Array<{field: string, key: string}> | Record<string, {key: string}>} obj - The error object to format
 * @returns {Array<{
 *   field: string,
 *   key: string,
 *   id: number
 * }> } Array of formatted error objects
 */
export function formatError(obj) {
	const errors = [];
	if (typeof obj === 'object') {
		if (Array.isArray(obj)) {
			obj.forEach((error) => {
				errors.push({
					field: error.field,
					key: error.key,
					id: Math.random() * 1000
				});
			});
		} else {
			Object.keys(obj).forEach((field) => {
				errors.push({
					field: field,
					key: obj[field].key,
					id: Math.random() * 1000
				});
			});
		}
	} else {
		errors.push({
			field: 'general',
			key: obj,
			id: 0
		});
	}
	return errors;
}

/**
 *
 * @param {string | null} newToken - The new token for the cookie to set
 * @param {import('@sveltejs/kit').Cookies } cookies - The event object
 */
export function refreshCookie(newToken, cookies) {
	if (newToken) {
		const match = newToken.match(/jwt=([^;]+)/);
		if (match) {
			cookies.set('jwt', match[1], {
				path: '/',
				httpOnly: true,
				secure: process.env.NODE_ENV === 'production', // Secure in production
				sameSite: 'lax',
				maxAge: 5 * 24 * 60 * 60 // 5 days in seconds
			});
		}
	}
}
