import * as Turbo from '@hotwired/turbo';

Turbo.session.drive = true;

const FRAMES = ['main-content', 'admin-content', 'auth-content'];

function isExternalLink(link) {
    return link.hostname !== window.location.hostname;
}

function disableTurboOnSpecialForms(root = document) {
    root.querySelectorAll('form[enctype="multipart/form-data"]').forEach((form) => {
        // Keep create/edit uploads inside the admin Turbo frame
        if (form.closest('turbo-frame#admin-content')) {
            form.setAttribute('data-turbo-frame', 'admin-content');
            form.removeAttribute('data-turbo');
            return;
        }
        form.setAttribute('data-turbo', 'false');
    });

    root.querySelectorAll('form[action*="logout"]').forEach((form) => {
        form.setAttribute('data-turbo', 'false');
    });
}

function wireAdminNavigation(root = document) {
    const frame = root.id === 'admin-content'
        ? root
        : root.querySelector?.('turbo-frame#admin-content') ?? document.getElementById('admin-content');

    if (!frame) return;

    frame.querySelectorAll('a[href]:not([data-turbo-frame])').forEach((link) => {
        if (link.getAttribute('data-turbo') === 'false' || link.target === '_blank') return;

        let path;
        try {
            path = new URL(link.href, window.location.origin).pathname;
        } catch {
            return;
        }

        if (path.startsWith('/admin')) {
            link.setAttribute('data-turbo-frame', 'admin-content');
        }
    });

    frame.querySelectorAll('form:not([data-turbo-frame])').forEach((form) => {
        if (form.getAttribute('data-turbo') === 'false' || form.action?.includes('logout')) return;
        form.setAttribute('data-turbo-frame', 'admin-content');
        if (form.enctype === 'multipart/form-data') {
            form.removeAttribute('data-turbo');
        }
    });
}

function wireOAuthLinks(root = document) {
    root.querySelectorAll('a[href*="/auth/"][href*="/redirect"]:not([data-oauth-wired])').forEach((link) => {
        link.setAttribute('data-oauth-wired', '1');
        link.setAttribute('data-turbo', 'false');
        link.setAttribute('target', '_top');
    });
}

function wirePagination(frame) {
    if (!frame?.id) return;

    frame.querySelectorAll('.pagination a, nav[role="navigation"] a').forEach((link) => {
        link.setAttribute('data-turbo-frame', frame.id);
    });
}

function updateNavActiveState(frame) {
    const path = window.location.pathname;
    const scope = frame?.id === 'admin-content'
        ? document.querySelector('.admin-sidebar')
        : document.querySelector('.navbar-mj, .mobile-bottom-nav');

    if (!scope) return;

    scope.querySelectorAll('a[href]').forEach((link) => {
        if (isExternalLink(link) || link.getAttribute('data-turbo') === 'false') return;

        const href = link.getAttribute('href');
        if (!href || href.startsWith('#')) return;

        let linkPath;
        try {
            linkPath = new URL(link.href).pathname;
        } catch {
            return;
        }

        const isActive = path === linkPath
            || (linkPath !== '/' && path.startsWith(linkPath));

        link.classList.toggle('active', isActive);
        link.classList.toggle('text-danger', isActive && frame?.id !== 'admin-content');
        link.classList.toggle('fw-bold', isActive && frame?.id !== 'admin-content');

        if (frame?.id === 'admin-content') {
            link.classList.toggle('active', isActive);
        }
    });

    document.querySelectorAll('.mobile-bottom-nav .nav-item-mobile').forEach((item) => {
        const href = item.getAttribute('href');
        if (!href) return;
        try {
            const linkPath = new URL(item.href, window.location.origin).pathname;
            item.classList.toggle('active', path === linkPath || (linkPath !== '/' && path.startsWith(linkPath)));
        } catch {
            // ignore invalid URLs
        }
    });
}

function runFrameScripts(frame) {
    frame.querySelectorAll('script[data-turbo-eval="true"]').forEach((oldScript) => {
        const script = document.createElement('script');
        if (oldScript.src) {
            script.src = oldScript.src;
        } else {
            script.textContent = oldScript.textContent;
        }
        if (oldScript.type) script.type = oldScript.type;
        oldScript.replaceWith(script);
    });
}

function handleFlashMessages(root = document) {
    const success = root.querySelector('[data-flash-success]');
    const error = root.querySelector('[data-flash-error]');
    const warning = root.querySelector('[data-flash-warning]');
    const info = root.querySelector('[data-flash-info]');

    if (success && window.Swal) {
        Swal.fire({
            icon: 'success',
            title: 'Success',
            text: success.dataset.flashSuccess,
            timer: 3500,
            timerProgressBar: true,
            showConfirmButton: false,
            toast: true,
            position: 'top-end',
        });
        success.remove();
    }

    if (error && window.Swal) {
        Swal.fire({ icon: 'error', title: 'Error', text: error.dataset.flashError, confirmButtonColor: '#f97316' });
        error.remove();
    }

    if (warning && window.Swal) {
        Swal.fire({ icon: 'warning', title: 'Notice', text: warning.dataset.flashWarning, confirmButtonColor: '#f97316' });
        warning.remove();
    }

    if (info && window.Swal) {
        Swal.fire({ icon: 'info', title: 'Info', text: info.dataset.flashInfo, confirmButtonColor: '#f97316' });
        info.remove();
    }
}

function onFrameReady(frame) {
    if (!frame) return;

    disableTurboOnSpecialForms(frame);
    wireOAuthLinks(frame);
    wireAdminNavigation(frame);
    wirePagination(frame);
    updateNavActiveState(frame);
    runFrameScripts(frame);
    handleFlashMessages(frame);

    window.dispatchEvent(new CustomEvent('turbo:page-ready', { detail: { frame } }));

    if (frame.scrollTop > 0) {
        frame.scrollTop = 0;
    }

    if (!document.body.classList.contains('admin-layout')) {
        window.scrollTo({ top: 0, behavior: 'smooth' });
    }
}

document.addEventListener('turbo:frame-missing', (event) => {
    event.preventDefault();
    event.detail.visit(event.detail.response);
});

document.addEventListener('turbo:load', () => {
    disableTurboOnSpecialForms();
    wireOAuthLinks();
    wireAdminNavigation();
    handleFlashMessages();

    FRAMES.forEach((id) => {
        const frame = document.getElementById(id);
        if (frame) onFrameReady(frame);
    });
});

document.addEventListener('turbo:frame-render', (event) => {
    onFrameReady(event.target);
});

document.addEventListener('turbo:frame-load', (event) => {
    const title = event.target.querySelector('[data-page-title]');
    if (title) {
        document.title = title.dataset.pageTitle;
    }
});

document.addEventListener('turbo:before-fetch-request', (event) => {
    const frame = event.target;
    if (frame?.tagName === 'TURBO-FRAME') {
        frame.classList.add('turbo-frame-loading');
    }
});

document.addEventListener('turbo:frame-render', (event) => {
    event.target.classList.remove('turbo-frame-loading');
});

document.addEventListener('turbo:submit-start', () => {
    document.body.classList.add('turbo-loading');
});

document.addEventListener('turbo:submit-end', () => {
    document.body.classList.remove('turbo-loading');
});
