// modules/core/click-manager.js
import { Logger } from './logger.js';
import { useEvent } from './useEvent.js';
import {navigateTo} from "./navigateTo";
import {SimpleCache} from "../utils/cache";

let callback = null;
let unsubscribes = [];
let cleanupInterval = null;
const prefetchCache = new SimpleCache(20, 60000); //new Map();
const maxCacheSize = 20; // max. Anzahl gecachter Seiten
const cacheTTL = 60000;  // Lebensdauer in ms (60s)

function isInternal(link) {
    return link.origin === location.origin;
}

function handleClick(e) {
    const link = e.target.closest('a');
    if (!link || e.defaultPrevented) return;

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

    // Skip conditions
    if (
        link.target === '_blank' ||
        link.hasAttribute('download') ||
        link.getAttribute('rel')?.includes('external') ||
        link.hasAttribute('data-skip')
    ) {
        Logger.info(`[click-manager] skipped: ${href}`);
        return;
    }

    if (isInternal(link)) {
        e.preventDefault();

        const cached = prefetchCache.get(href);
        const valid = cached && Date.now() - cached.timestamp < cacheTTL;

        const options = {
            viewTransition: link.hasAttribute('data-view-transition'),
            replace: link.hasAttribute('data-replace'),
            modal: link.hasAttribute('data-modal'),
            prefetched: valid,
            data: valid ? cached.data : null,
        };

        Logger.info(`[click-manager] internal: ${href}`, options);

        if(options.modal) {
            callback?.(href, link, options);
        } else {
            navigateTo(href, options);
        }
    }
}

let prefetchTimeout;
function handleMouseOver(e) {
    clearTimeout(prefetchTimeout);
    const link = e.target.closest('a[href]');
    if (!link || !isInternal(link)) return;

    const href = link.getAttribute('href');
    if (!href || prefetchCache.has(href)) return;

    // optional: Wait 150ms to reduce noise
    prefetchTimeout = setTimeout(() => prefetch(href), 150);
}

function prefetch(href) {
    Logger.info(`[click-manager] prefetching: ${href}`);

    fetch(href)
        .then(res => res.text())
        .then(html => {
            if (prefetchCache.cache.size >= maxCacheSize) {
                const oldestKey = [...prefetchCache.cache.entries()].sort((a, b) => a[1].timestamp - b[1].timestamp)[0][0];
                prefetchCache.cache.delete(oldestKey);
            }
            prefetchCache.set(href, {
                data: html,
                timestamp: Date.now(),
            });
        })
        .catch(err => {
            Logger.warn(`[click-manager] prefetch failed for ${href}`, err);
        });
}

function handlePopState() {
    const href = location.pathname;
    Logger.info(`[click-manager] popstate: ${href}`);
    navigateTo(href, { replace: true });
}

export function getPrefetched(href) {
    const cached = prefetchCache.get(href);
    const valid = cached && Date.now() - cached.timestamp < cacheTTL;
    return valid ? cached.data : null;
}

export function prefetchHref(href) {
    if (!href || prefetchCache.has(href)) return;
    prefetch(href);
}

export function init(onNavigate) {
    callback = onNavigate;
    unsubscribes = [
        useEvent(document, 'click', handleClick),
        useEvent(document, 'mouseover', handleMouseOver),
        useEvent(window, 'popstate', handlePopState),
    ]

    cleanupInterval = setInterval(() => {
        for (const [key, val] of prefetchCache.cache.entries()) {
            if (Date.now() - val.timestamp > prefetchCache.ttl) {
                prefetchCache.cache.delete(key);
            }
        }
    }, 120000);


    Logger.info('[click-manager] ready');
}

export function destroy() {
    callback = null;
    prefetchCache.clear();
    unsubscribes.forEach(unsub => unsub());
    unsubscribes = [];
    Logger.info('[click-manager] destroyed');
}
