import { BodyType } from './functions/send-crisp-message.js'

type CamelCase<S extends string> =
	S extends `${infer P1}_${infer P2}${infer P3}`
		? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
		: Lowercase<S>

const snakeToCamelCase = <T extends string>(str: T) =>
	str
		.replace(/_/g, ' ')
		.replace(/(?<!\p{L})\p{L}|\s+/gu, (m) => (+m === 0 ? '' : m.toUpperCase()))
		.replace(/^./, (m) => m?.toLowerCase()) as CamelCase<T>

export type KeysToCamelCase<T> = {
	[K in keyof T as CamelCase<string & K>]: T[K]
}

export const snakeToCamelCaseKeys = <T extends object>(object: T) =>
	Object.fromEntries(
		Object.entries(object).map(
			([key, value]) => [snakeToCamelCase(key), value],
			{}
		)
	) as KeysToCamelCase<T>

export const shuffleArray = <T>(array: T[]) => {
	const shuffle = [...array]

	for (let i = shuffle.length - 1; i > 0; i--) {
		const j = Math.floor(Math.random() * (i + 1))
		const [shuffleI, shuffleJ] = [shuffle[i], shuffle[j]]
		shuffle[i] = shuffleJ
		shuffle[j] = shuffleI
	}

	return shuffle
}

const isStringAndNotEmpty = (value: string) =>
	value !== undefined && value !== '' && typeof value === 'string'

const SHORT_MAX_LENGTH = 254

export const validateCrispBody = (body: BodyType): BodyType => {
	const { subject, message, email } = body || {}
	if (
		isStringAndNotEmpty(subject) &&
		subject.length <= SHORT_MAX_LENGTH &&
		isStringAndNotEmpty(message) &&
		isStringAndNotEmpty(email) &&
		email.length <= SHORT_MAX_LENGTH
	) {
		return body
	}

	throw Error('Body validation failed.')
}