(function () {
    const messageTypes = {
        ready: 'supportdesk:ready',
        auth: 'supportdesk:auth',
        logout: 'supportdesk:logout',
        tokenExpired: 'supportdesk:token-expired',
        resize: 'supportdesk:resize',
    };

    function resolveIframe(iframe) {
        if (iframe instanceof HTMLIFrameElement) {
            return iframe;
        }

        if (typeof iframe === 'string') {
            return document.querySelector(iframe);
        }

        return null;
    }

    async function buildAuthPayload(options) {
        if (typeof options.getAuth === 'function') {
            return await options.getAuth();
        }

        if (typeof options.getToken === 'function') {
            return { token: await options.getToken() };
        }

        if (options.auth && typeof options.auth === 'object') {
            return options.auth;
        }

        return null;
    }

    function mount(options) {
        const iframe = resolveIframe(options.iframe);

        if (!iframe) {
            throw new Error('SupportDeskEmbed could not find the iframe element.');
        }

        const targetOrigin = options.targetOrigin || new URL(iframe.src, window.location.href).origin;

        async function sendAuth(reason) {
            const authPayload = await buildAuthPayload(options);

            if (!authPayload || !authPayload.token) {
                if (typeof options.onAuthMissing === 'function') {
                    options.onAuthMissing({ reason });
                }
                return;
            }

            iframe.contentWindow?.postMessage(
                {
                    type: messageTypes.auth,
                    reason,
                    token: authPayload.token,
                    user: authPayload.user || null,
                    message: authPayload.message || undefined,
                },
                targetOrigin
            );
        }

        async function handleMessage(event) {
            if (event.origin !== targetOrigin || event.source !== iframe.contentWindow) {
                return;
            }

            const payload = event.data || {};

            if (payload.type === messageTypes.ready) {
                await sendAuth(payload.reason || 'iframe_ready');
            } else if (payload.type === messageTypes.tokenExpired) {
                if (typeof options.onTokenExpired === 'function') {
                    await options.onTokenExpired(payload);
                }
                await sendAuth('token_expired');
            } else if (payload.type === messageTypes.logout) {
                if (typeof options.onLogout === 'function') {
                    options.onLogout(payload);
                }
            } else if (payload.type === messageTypes.resize && payload.height) {
                if (options.autoResize !== false) {
                    iframe.style.height = `${payload.height}px`;
                }
            }
        }

        function handleLoad() {
            sendAuth('iframe_load');
        }

        window.addEventListener('message', handleMessage);
        iframe.addEventListener('load', handleLoad);

        return {
            refreshAuth: () => sendAuth('manual_refresh'),
            destroy() {
                window.removeEventListener('message', handleMessage);
                iframe.removeEventListener('load', handleLoad);
            },
        };
    }

    window.SupportDeskEmbed = {
        mount,
        messageTypes,
    };
})();
