import './bootstrap';

import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm';
import ApexCharts from 'apexcharts';

window.Alpine = Alpine;
window.Livewire = Livewire;
window.ApexCharts = ApexCharts;

Livewire.start();

/* ------------------------------------------------------------------ */
/*  Global AsignaPro loader                                            */
/* ------------------------------------------------------------------ */
const APP_LOADER_ID = 'asignapro-global-loader';
let appLoaderHideTimer = null;
let appLoaderVisibleSince = 0;

function ensureAppLoader() {
    let loader = document.getElementById(APP_LOADER_ID);

    if (loader) return loader;

    loader = document.createElement('div');
    loader.id = APP_LOADER_ID;
    loader.className = 'ap-loader';
    loader.setAttribute('aria-live', 'polite');
    loader.setAttribute('aria-label', 'Cargando');
    loader.innerHTML = `
        <div class="ap-loader-card" role="status">
            <span class="ap-loader-ring" aria-hidden="true"></span>
            <img class="ap-loader-logo" src="/assets/brand/loading-logo.png" alt="AsignaPro">
            <span class="ap-loader-text">Cargando</span>
        </div>
    `;

    document.body.appendChild(loader);

    return loader;
}

function showAppLoader() {
    const loader = ensureAppLoader();
    window.clearTimeout(appLoaderHideTimer);
    appLoaderVisibleSince = appLoaderVisibleSince || Date.now();
    loader.classList.add('is-visible');
    document.documentElement.classList.add('ap-loader-lock');
    appLoaderHideTimer = window.setTimeout(() => hideAppLoader(0), 12000);
}

function hideAppLoader(minVisible = 360) {
    const loader = document.getElementById(APP_LOADER_ID);
    if (!loader) return;

    const elapsed = appLoaderVisibleSince ? Date.now() - appLoaderVisibleSince : minVisible;
    const delay = Math.max(0, minVisible - elapsed);

    window.clearTimeout(appLoaderHideTimer);
    appLoaderHideTimer = window.setTimeout(() => {
        loader.classList.remove('is-visible');
        document.documentElement.classList.remove('ap-loader-lock');
        appLoaderVisibleSince = 0;
    }, delay);
}

window.asignaLoader = {
    show: showAppLoader,
    hide: hideAppLoader,
};

document.addEventListener('DOMContentLoaded', () => {
    showAppLoader();
});

window.addEventListener('load', () => {
    hideAppLoader(520);
});

window.addEventListener('pageshow', () => {
    hideAppLoader(180);
});

document.addEventListener('click', (event) => {
    const livewireAction = event.target.closest('[wire\\:click], [data-public-service-id]');
    if (livewireAction) {
        showAppLoader();
    }

    const link = event.target.closest('a[href]');
    if (!link) return;

    const href = link.getAttribute('href') || '';
    const isExternal = link.origin && link.origin !== window.location.origin;
    const isNewContext = link.target === '_blank' || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
    const isAnchorOnly = href.startsWith('#') || href === window.location.pathname + window.location.hash;
    const isDownload = link.hasAttribute('download');

    if (isExternal || isNewContext || isAnchorOnly || isDownload || href.startsWith('mailto:') || href.startsWith('tel:')) {
        return;
    }

    showAppLoader();
});

document.addEventListener('submit', (event) => {
    const form = event.target;
    if (!(form instanceof HTMLFormElement)) return;

    if (form.dataset.noLoader === 'true') return;

    showAppLoader();
});

try {
    window.Livewire?.hook?.('request', ({ respond, succeed, fail }) => {
        respond?.(() => hideAppLoader(260));
        succeed?.(() => hideAppLoader(260));
        fail?.(() => hideAppLoader(260));
    });
} catch (_) {
    document.addEventListener('livewire:load', () => hideAppLoader(260));
}

/* ------------------------------------------------------------------ */
/*  Sileo-style toast alerts                                           */
/* ------------------------------------------------------------------ */
const SILEO_STYLE_ID = 'reservapro-sileo-style';

function ensureSileoStyles() {
    if (document.getElementById(SILEO_STYLE_ID)) return;

    const style = document.createElement('style');
    style.id = SILEO_STYLE_ID;
    style.textContent = `
        .sileo-stack {
            position: fixed;
            top: 22px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 9999;
            display: grid;
            gap: 10px;
            width: min(440px, calc(100vw - 32px));
            pointer-events: none;
        }
        .sileo-toast {
            pointer-events: auto;
            display: flex;
            align-items: flex-start;
            gap: 12px;
            padding: 14px 16px;
            border-radius: 18px;
            background: rgba(255, 255, 255, .94);
            border: 1px solid rgba(226, 232, 240, .95);
            box-shadow: 0 20px 45px rgba(15, 23, 42, .16);
            backdrop-filter: blur(16px);
            transform: translateY(-12px) scale(.96);
            opacity: 0;
            animation: sileo-in .28s cubic-bezier(.2, .9, .25, 1.25) forwards;
        }
        .sileo-toast.is-leaving {
            animation: sileo-out .2s ease forwards;
        }
        .sileo-mark {
            width: 28px;
            height: 28px;
            border-radius: 999px;
            display: grid;
            place-items: center;
            color: white;
            font-weight: 900;
            flex: 0 0 auto;
        }
        .sileo-toast.success .sileo-mark { background: #10b981; }
        .sileo-toast.error .sileo-mark { background: #e11d48; }
        .sileo-toast.warning .sileo-mark { background: #f59e0b; }
        .sileo-body { min-width: 0; }
        .sileo-title { margin: 0; font-size: 14px; font-weight: 900; color: #0f172a; }
        .sileo-message { margin: 2px 0 0; font-size: 13px; line-height: 1.35; color: #475569; }
        .sileo-close {
            margin-left: auto;
            border: 0;
            background: transparent;
            color: #94a3b8;
            font-size: 18px;
            line-height: 1;
            cursor: pointer;
        }
        @keyframes sileo-in {
            to { transform: translateY(0) scale(1); opacity: 1; }
        }
        @keyframes sileo-out {
            to { transform: translateY(-10px) scale(.98); opacity: 0; }
        }
    `;
    document.head.appendChild(style);
}

function sileoToast(type, message, title = null, timeout = 4200) {
    ensureSileoStyles();

    let stack = document.querySelector('.sileo-stack');
    if (!stack) {
        stack = document.createElement('div');
        stack.className = 'sileo-stack';
        document.body.appendChild(stack);
    }

    const labels = {
        success: ['Actualizado', '✓'],
        error: ['Error', '!'],
        warning: ['Atención', '!'],
    };
    const [fallbackTitle, mark] = labels[type] || labels.success;
    const toast = document.createElement('div');
    toast.className = `sileo-toast ${type}`;
    toast.innerHTML = `
        <span class="sileo-mark">${mark}</span>
        <div class="sileo-body">
            <p class="sileo-title">${title || fallbackTitle}</p>
            <p class="sileo-message"></p>
        </div>
        <button type="button" class="sileo-close" aria-label="Cerrar">&times;</button>
    `;
    toast.querySelector('.sileo-message').textContent = message;

    const close = () => {
        toast.classList.add('is-leaving');
        setTimeout(() => toast.remove(), 220);
    };

    toast.querySelector('.sileo-close').addEventListener('click', close);
    stack.appendChild(toast);
    setTimeout(close, timeout);
}

window.sileo = {
    success: (message, title = 'Actualizado') => sileoToast('success', message, title),
    error: (message, title = 'Error') => sileoToast('error', message, title),
    warning: (message, title = 'Atención') => sileoToast('warning', message, title),
};

window.addEventListener('sileo:toast', (event) => {
    const detail = event.detail || {};
    sileoToast(detail.type || 'success', detail.message || '', detail.title || null);
});

/* ------------------------------------------------------------------ */
/*  PWA — Service worker registration                                  */
/* ------------------------------------------------------------------ */
if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
        navigator.serviceWorker.register('/sw.js').catch(() => {});
    });
}

/* ------------------------------------------------------------------ */
/*  PWA — Push notifications                                           */
/* ------------------------------------------------------------------ */
function urlBase64ToUint8Array(base64String) {
    const padding = '='.repeat((4 - base64String.length % 4) % 4);
    const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);

    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }

    return outputArray;
}

function pushPublicKey() {
    return document.querySelector('meta[name="webpush-vapid-public-key"]')?.content || '';
}

function pushIsSupported() {
    return Boolean(pushPublicKey()) && 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window;
}

function hasPushTriggers() {
    return document.querySelector('[data-push-enable]') !== null;
}

function applyPushButtonState() {
    if (!pushIsSupported()) return;

    document.querySelectorAll('[data-push-enable]').forEach((el) => {
        el.hidden = false;

        const label = el.querySelector('[data-push-label]');

        el.classList.remove('is-push-blocked', 'is-push-active');

        if (Notification.permission === 'granted') {
            el.hidden = true;
            el.classList.add('is-push-active');
            if (label) label.textContent = 'Avisos activos';
            return;
        }

        if (Notification.permission === 'denied') {
            el.classList.add('is-push-blocked');
            el.title = 'Las notificaciones están bloqueadas en este navegador';
            if (label) label.textContent = 'Avisos bloqueados';
            return;
        }

        el.title = 'Activar notificaciones de reservas y cancelaciones';
        if (label) label.textContent = 'Activar avisos';
    });
}

async function savePushSubscription(subscription) {
    const csrf = document.querySelector('meta[name="csrf-token"]')?.content || '';
    const payload = subscription.toJSON();

    await fetch('/push-subscriptions', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': csrf,
        },
        body: JSON.stringify({
            endpoint: payload.endpoint,
            keys: payload.keys,
            contentEncoding: PushManager.supportedContentEncodings?.includes('aes128gcm') ? 'aes128gcm' : 'aesgcm',
        }),
    });
}

async function ensurePushSubscription({ notify = false } = {}) {
    if (!pushIsSupported() || !hasPushTriggers()) return false;

    if (Notification.permission === 'denied') {
        if (notify) {
            window.sileo?.warning('Chrome bloqueó los avisos para este sitio. Toca el candado de la barra de direcciones, entra a Permisos y cambia Notificaciones a Permitir.', 'Notificaciones bloqueadas');
        }
        applyPushButtonState();
        return false;
    }

    const registration = await navigator.serviceWorker.ready;
    let subscription = await registration.pushManager.getSubscription();

    if (!subscription) {
        if (Notification.permission !== 'granted') {
            const permission = await Notification.requestPermission();
            if (permission !== 'granted') {
                if (notify) window.sileo?.warning('No activaste los avisos. Puedes intentarlo de nuevo cuando quieras.', 'Avisos pendientes');
                applyPushButtonState();
                return false;
            }
        }

        subscription = await registration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(pushPublicKey()),
        });
    }

    await savePushSubscription(subscription);

    if (notify) {
        window.sileo?.success('Te avisaremos cuando entren reservas o cancelaciones.', 'Avisos activados');
    }

    document.querySelectorAll('[data-push-enable]').forEach((el) => {
        el.hidden = true;
    });
    applyPushButtonState();

    return true;
}

function refreshPushTriggers() {
    if (!pushIsSupported() || !hasPushTriggers()) return;
    applyPushButtonState();

    if (Notification.permission === 'granted') {
        ensurePushSubscription().catch(() => {});
    }
}

document.addEventListener('click', (event) => {
    const trigger = event.target.closest('[data-push-enable]');
    if (!trigger) return;

    ensurePushSubscription({ notify: true }).catch(() => {
        window.sileo?.error('No pudimos activar las notificaciones en este dispositivo.', 'Error de avisos');
    });
});

window.addEventListener('load', refreshPushTriggers);

/* ------------------------------------------------------------------ */
/*  PWA — Install prompt                                               */
/* ------------------------------------------------------------------ */
const PWA_DISMISS_KEY   = 'pwa_dismissed_until';
const PWA_INSTALLED_KEY = 'pwa_installed';

let deferredInstallPrompt = null;

function pwaIsInstalled() {
    if (localStorage.getItem(PWA_INSTALLED_KEY) === '1') return true;
    if (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) return true;
    if (window.navigator.standalone) return true; // iOS Safari
    return false;
}

function pwaIsIos() {
    return /iphone|ipad|ipod/i.test(window.navigator.userAgent || '') ||
        (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
}

function pwaIsDismissed() {
    const until = Number(localStorage.getItem(PWA_DISMISS_KEY) || 0);
    return until > Date.now();
}

function showInstallTriggers() {
    if (pwaIsInstalled() || pwaIsDismissed()) return;
    document.querySelectorAll('[data-pwa-install]').forEach(el => el.hidden = false);
    if (pwaIsIos() && !deferredInstallPrompt) {
        document.querySelectorAll('[data-pwa-ios-hint]').forEach(el => el.hidden = false);
    }
}

function hideInstallTriggers() {
    document.querySelectorAll('[data-pwa-install]').forEach(el => el.hidden = true);
}

window.addEventListener('beforeinstallprompt', (event) => {
    event.preventDefault();
    deferredInstallPrompt = event;
    showInstallTriggers();
});

document.addEventListener('click', async (e) => {
    // Botón topbar o botón "Instalar" dentro del banner
    const trigger = e.target.closest('button[data-pwa-install], [data-pwa-install-trigger]');
    if (!trigger) return;

    if (!deferredInstallPrompt) {
        if (pwaIsIos()) {
            window.sileo?.warning('En iPhone toca el botón Compartir y luego “Agregar a pantalla de inicio”.', 'Instalar AsignaPro');
        }
        return;
    }

    deferredInstallPrompt.prompt();
    const { outcome } = await deferredInstallPrompt.userChoice;
    deferredInstallPrompt = null;
    hideInstallTriggers();

    if (outcome === 'accepted') {
        localStorage.setItem(PWA_INSTALLED_KEY, '1');
    }
});

window.addEventListener('appinstalled', () => {
    deferredInstallPrompt = null;
    localStorage.setItem(PWA_INSTALLED_KEY, '1');
    hideInstallTriggers();
});

window.addEventListener('load', () => {
    if (pwaIsIos()) showInstallTriggers();
});

window.addEventListener('offline', () => {
    window.sileo?.warning('Algunas acciones pueden no estar disponibles hasta recuperar internet.', 'Sin conexión');
});

window.addEventListener('online', () => {
    window.sileo?.success('La conexión volvió. Ya puedes seguir trabajando.', 'Conectado');
});
