export class TimeoutError extends Error {
    constructor(message) {
        super(message);
        this.name = 'TimeoutError';
    }
}

export function _(key, substitutions) {
    try {
        return chrome.i18n.getMessage(key, substitutions);
    } catch (e) {
        return key;
    }
}

export function showNotification(message, type = 'info', duration = 3000) {
    const notificationContainer = document.getElementById('notification-container');
    const template = document.getElementById('notification-template');

    if (!notificationContainer || !template) {
        alert(`${type.toUpperCase()}: ${message}`);
        return;
    }

    const notificationClone = template.querySelector('.notification').cloneNode(true);
    notificationClone.className = `notification ${type}`;

    const icon = notificationClone.querySelector('i');
    const span = notificationClone.querySelector('span');
    span.textContent = message;

    let iconClass = 'fa-info-circle';
    if (type === 'success') iconClass = 'fa-check-circle';
    else if (type === 'error') iconClass = 'fa-exclamation-triangle';
    else if (type === 'warning') iconClass = 'fa-exclamation-circle';
    icon.className = `fas ${iconClass}`;

    notificationContainer.prepend(notificationClone);

    setTimeout(() => {
        notificationClone.classList.add('show');
    }, 50);

    setTimeout(() => {
        notificationClone.classList.remove('show');
        notificationClone.addEventListener('transitionend', () => notificationClone.remove(), { once: true });
    }, duration);
}

export function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func.apply(this, args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

export function getRelativeTime(timestamp) {
    const now = Date.now();
    const diffSeconds = Math.round((now - timestamp) / 1000);
    const diffMinutes = Math.round(diffSeconds / 60);
    const diffHours = Math.round(diffMinutes / 60);
    const diffDays = Math.round(diffHours / 24);

    if (diffSeconds < 60) return _('relativeTime_justNow');
    if (diffMinutes < 60) return _('relativeTime_minutesAgo', String(diffMinutes));
    if (diffHours < 24) return _('relativeTime_hoursAgo', String(diffHours));
    if (diffDays === 1) return _('relativeTime_yesterday');
    if (diffDays < 7) return _('relativeTime_daysAgo', String(diffDays));
    
    return (new Date(timestamp)).toLocaleDateString(_('appLocaleCode'), { day: 'numeric', month: 'short' });
}

export function mostrarSpinner() {
    const spinner = document.getElementById('spinner');
    if (spinner) spinner.style.display = 'block';
}

export function ocultarSpinner() {
    const spinner = document.getElementById('spinner');
    if (spinner) spinner.style.display = 'none';
}

export function logToConsole(message) {
    const consoleOutput = document.getElementById('consoleOutput');
    if (!consoleOutput) return;

    const logEntry = document.createElement('div');
    logEntry.className = 'console-log-entry';
    const time = new Date().toLocaleTimeString(_('appLocaleCode'), { hour12: false });
    
    const timeSpan = `<span class="log-time">[${time}]</span>`;
    const messageSpan = `<span class="log-message">${message.replace(/</g, "<").replace(/>/g, ">")}</span>`;

    if (message.toLowerCase().includes("error")) {
        logEntry.classList.add('log-error');
    } else if (message.toLowerCase().includes("advertencia") || message.toLowerCase().includes("warning") || message.toLowerCase().includes("pendiente")) {
        logEntry.classList.add('log-warning');
    } else if (message.toLowerCase().includes("success") || message.toLowerCase().includes("finalizado") || message.toLowerCase().includes("éxito") || message.toLowerCase().includes("limpiadas")) {
        logEntry.classList.add('log-success');
    }
    
    logEntry.innerHTML = `${timeSpan} ${messageSpan}`;
    consoleOutput.appendChild(logEntry);
    consoleOutput.scrollTop = consoleOutput.scrollHeight;
}

export function emitirEventoActualizacion() {
    const event = new CustomEvent('indexedDBUpdated');
    window.dispatchEvent(event);
}

export async function fetchWithTimeout(url, options, timeout = 7000) {
    return new Promise((resolve, reject) => {
        const controller = new AbortController();
        const signal = controller.signal;
        
        const timer = setTimeout(() => {
            controller.abort();
            reject(new TimeoutError(`Timeout(${timeout}ms)`));
        }, timeout);

        fetch(url, { ...options, signal })
            .then(response => { clearTimeout(timer); resolve(response); })
            .catch(err => {
                clearTimeout(timer);
                if (err.name === 'AbortError') {
                    reject(new TimeoutError(`Timeout(${timeout}ms)`));
                } else {
                    reject(err);
                }
            });
    });
}