import { startAuthentication, startRegistration } from '@simplewebauthn/browser';
import * as z from 'zod';
import { fetchAPI } from './requests.js';
import Cache from './cache.js';
export async function login(userId) {
    const options = await fetchAPI('PUT', 'users/:id/auth', { type: 'login' }, userId);
    const response = await startAuthentication({ optionsJSON: options });
    return await fetchAPI('POST', 'users/:id/auth', response, userId);
}
/**
 * Create an elevated session for the user to perform sensitive actions.
 */
export async function elevate(userId) {
    const options = await fetchAPI('PUT', 'users/:id/auth', { type: 'action' }, userId);
    const response = await startAuthentication({ optionsJSON: options });
    await fetchAPI('POST', 'users/:id/auth', response, userId);
}
export async function loginByEmail(email) {
    const { id: userId } = await fetchAPI('POST', 'user_id', {
        using: 'email',
        value: email,
    });
    return await login(userId);
}
let _currentSession = null;
export async function getCurrentSession() {
    _currentSession ||= await fetchAPI('GET', 'session');
    return _currentSession;
}
export async function getSessions(userId) {
    _checkId(userId);
    return await fetchAPI('GET', 'users/:id/sessions', {}, userId);
}
export async function logout(userId, ...sessionId) {
    _checkId(userId);
    return await fetchAPI('DELETE', 'users/:id/sessions', { id: sessionId }, userId);
}
export async function logoutAll(userId) {
    _checkId(userId);
    await elevate(userId);
    return await fetchAPI('DELETE', 'users/:id/sessions', { confirm_all: true }, userId);
}
export async function logoutCurrentSession() {
    return await fetchAPI('DELETE', 'session');
}
export async function register(_data) {
    const data = z.object({ name: z.string(), email: z.email() }).parse(_data);
    const { options, userId } = await fetchAPI('PUT', 'register', data);
    const response = await startRegistration({ optionsJSON: options });
    await fetchAPI('POST', 'register', {
        userId,
        name: data.name,
        email: data.email,
        response,
    });
}
function _checkId(userId) {
    try {
        z.uuid().parse(userId);
    }
    catch (e) {
        throw e instanceof z.core.$ZodError ? z.prettifyError(e) : e;
    }
}
const userCache = new Cache((userId) => fetchAPI('GET', 'users/:id', {}, userId), { ttl: 86400_000 });
export { userCache as apiUserCache };
export async function userInfo(userId) {
    _checkId(userId);
    return await userCache.get(userId);
}
export async function updateUser(userId, data) {
    _checkId(userId);
    const result = await fetchAPI('PATCH', 'users/:id', data, userId);
    userCache.set(userId, result);
    return result;
}
export async function fullUserInfo(userId) {
    _checkId(userId);
    return await fetchAPI('GET', 'users/:id/full', {}, userId);
}
/**
 * @param userId The UUID of the user to delete
 * @param deletingId The UUID of the user performing the deletion (for authentication). Defaults to userId.
 */
export async function deleteUser(userId, deletingId = userId) {
    _checkId(userId);
    const options = await fetchAPI('PUT', 'users/:id/auth', { type: 'action' }, deletingId);
    const response = await startAuthentication({ optionsJSON: options });
    await fetchAPI('POST', 'users/:id/auth', response, deletingId);
    const result = await fetchAPI('DELETE', 'users/:id', response, userId);
    userCache.invalidate(userId);
    return result;
}
export async function emailVerificationEnabled(userId) {
    _checkId(userId);
    const { enabled } = await fetchAPI('OPTIONS', 'users/:id/verify/email', {}, userId);
    return enabled;
}
export async function sendVerificationEmail(userId) {
    _checkId(userId);
    return await fetchAPI('GET', 'users/:id/verify/email', {}, userId);
}
export async function verifyEmail(userId, token) {
    _checkId(userId);
    await fetchAPI('POST', 'users/:id/verify/email', { token }, userId);
}
export async function getPasskeys(userId) {
    _checkId(userId);
    return await fetchAPI('GET', 'users/:id/passkeys', {}, userId);
}
/**
 * Create a new passkey for an existing user.
 */
export async function createPasskey(userId) {
    _checkId(userId);
    const options = await fetchAPI('OPTIONS', 'users/:id/passkeys', {}, userId);
    const response = await startRegistration({ optionsJSON: options });
    return await fetchAPI('PUT', 'users/:id/passkeys', response, userId);
}
export async function updatePasskey(passkeyId, data) {
    return await fetchAPI('PATCH', 'passkeys/:id', data, passkeyId);
}
export async function deletePasskey(passkeyId) {
    return await fetchAPI('DELETE', 'passkeys/:id', {}, passkeyId);
}
