import {startAuthentication, startRegistration} from '@simplewebauthn/browser';
import {PasskeysOperationResult} from "@/types/service/passkeys";

export default class Passkeys {
    constructor(
        private readonly t: (translationKey: string) => string,
    ) {
    }

    private async postRequest(url: string, body: Object) {
        return fetch(url, {
            method: 'POST',
            body: JSON.stringify(body),
            headers: {'Content-Type': 'application/json'},
        })
    }

    public async registerPasskey(optionsUrl: string, resultUrl: string, username: string): Promise<PasskeysOperationResult> {
        const response = await this.postRequest(optionsUrl, {username});
        const options = await response.json();

        const assertationResponse = await startRegistration(options);
        const registration = await this.postRequest(resultUrl, assertationResponse);

        if (!registration.ok) {
            const response = await registration.json();
            return {
                success: false,
                messages: [{
                    message: response.errorMessage,
                    type: "danger"
                }],
            };
        }

        return {
            success: true,
            messages: [{
                message: this.t('admin.auth.passkeys.successfully-created-account'),
                type: "success"
            }],
        };
    };

    public async addPasskeyEntryToExistingUser(optionsUrl: string, resultUrl: string, uuid: string): Promise<PasskeysOperationResult> {
        const response = await this.postRequest(optionsUrl, {uuid});
        const options = await response.json();

        try {
            const assertationResponse = await startRegistration(options);
            const addPasskey = await this.postRequest(resultUrl, assertationResponse);

            if (!addPasskey.ok) {
                const response = await addPasskey.json();
                return {
                    success: false,
                    messages: [{
                        message: response.errorMessage,
                        type: "danger"
                    }],
                };
            }
        } catch (error) {
            let errorMessage = "";
            if (typeof error === "string") {
                errorMessage = error.toUpperCase();
            } else if (error instanceof Error) {
                errorMessage = error.message;
            }
            return {
                success: false,
                messages: [{
                    message: errorMessage,
                    type: "danger"
                }],
            };
        }

        return {
            success: true,
            messages: [{
                message: this.t('admin.auth.passkeys.successfully-added-new-credential'),
                type: "success"
            }],
        };
    }

    public async loginPasskey(optionsUrl: string, resultUrl: string, username: string): Promise<PasskeysOperationResult> {
        const response = await this.postRequest(optionsUrl, {username});
        const options = await response.json();

        const assertationResponse = await startAuthentication(options);
        const login = await this.postRequest(resultUrl, assertationResponse);

        if (!login.ok) {
            const response = await login.json();
            return {
                success: false,
                messages: [{
                    message: response.errorMessage,
                    type: "danger"
                }],
            };
        }

        return {
            success: true,
            messages: [],
        };
    };
}
