/**
 * Shared helpers for the log panel component.
 *
 * Extracted from components/logpanel.js so they can be unit-tested
 * (the logpanel.js IIFE is otherwise unreachable from tests).
 *
 * Exposes window.LdrLogHelpers. Consumers should destructure at the top
 * of their IIFE, e.g.
 *     const { checkLogVisibility, hashString } = window.LdrLogHelpers;
 */
(function() {
    'use strict';

    /**
     * Decide whether a log entry of the given type should be visible
     * under a filter selection. Matches the plural/singular variants the
     * UI may emit (e.g. "milestones" vs "milestone").
     * @param {string} logType - 'info' | 'milestone' | 'warning' | 'error'
     * @param {string} filterType - selected filter ('all', 'info', 'milestone', ...)
     * @returns {boolean}
     */
    function checkLogVisibility(logType, filterType) {
        switch (filterType) {
            case 'all':
                return true;
            case 'info':
                return logType === 'info' || logType === 'warning' || logType === 'milestone' || logType === 'error';
            case 'milestone':
            case 'milestones': // Handle plural form too
                return logType === 'milestone';
            case 'warning':
            case 'warnings':
                return logType === 'warning' || logType === 'error';
            case 'error':
            case 'errors': // Handle plural form too
                return logType === 'error';
            default:
                return true; // Default to showing everything
        }
    }

    /**
     * Deterministic 32-bit string hash, used to build stable IDs for
     * deduping log entries.
     * @param {string} str
     * @returns {string} The hash as a decimal string.
     */
    function hashString(str) {
        if (!str) return '0';
        let hash = 0;
        for (let i = 0; i < str.length; i++) {
            const char = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash &= hash; // Convert to 32bit integer
        }
        return hash.toString();
    }

    /**
     * Trim and lowercase a log message for deduplication comparison.
     * Null/undefined become the empty string.
     * @param {string} message
     * @returns {string}
     */
    function normalizeMessage(message) {
        if (!message) return '';
        return message.trim().toLowerCase();
    }

    /**
     * Normalize timestamps across a batch of logs so stray entries from
     * a different calendar day (clock skew, retries) are re-anchored to
     * the date most logs already share. Mutates `logs` in place.
     *
     * Uses a frequency count: the most common YYYY-MM-DD wins; logs on
     * other dates have their date re-stamped while preserving the time.
     * @param {Array<{time: string, message?: string, id?: string}>} logs
     */
    function normalizeTimestamps(logs) {
        // Find the most common date in the logs (ignoring the time)
        const dateFrequency = new Map();

        logs.forEach(log => {
            try {
                const date = new Date(log.time);
                // Extract just the date part (YYYY-MM-DD)
                const dateStr = date.toISOString().split('T')[0];
                dateFrequency.set(dateStr, (dateFrequency.get(dateStr) || 0) + 1);
            } catch {
                SafeLogger.error('Error parsing date:', log.time);
            }
        });

        // Find the most frequent date
        let mostCommonDate = null;
        let highestFrequency = 0;

        dateFrequency.forEach((count, date) => {
            if (count > highestFrequency) {
                highestFrequency = count;
                mostCommonDate = date;
            }
        });

        SafeLogger.log(`Most common date: ${mostCommonDate} with ${highestFrequency} occurrences`);

        if (!mostCommonDate) return; // Can't normalize without a common date

        // Normalize all logs to the most common date
        logs.forEach(log => {
            try {
                const date = new Date(log.time);
                const dateStr = date.toISOString().split('T')[0];

                // If this log is from a different date, adjust it to the most common date
                // while preserving the time portion
                if (dateStr !== mostCommonDate) {
                    const [year, month, day] = mostCommonDate.split('-');
                    date.setFullYear(parseInt(year, 10));
                    date.setMonth(parseInt(month, 10) - 1); // Months are 0-indexed
                    date.setDate(parseInt(day, 10));

                    // Update the log time
                    log.time = date.toISOString();
                    log.id = `${log.time}-${hashString(log.message)}`;
                    SafeLogger.log(`Normalized timestamp for "${log.message.substring(0, 30)}..." from ${dateStr} to ${mostCommonDate}`);
                }
            } catch {
                SafeLogger.error('Error normalizing date:', log.time);
            }
        });
    }

    window.LdrLogHelpers = {
        checkLogVisibility,
        hashString,
        normalizeMessage,
        normalizeTimestamps,
    };
})();
