/**
 * Entity event listeners — reacts to server-pushed entity_changed and
 * device_health_changed WebSocket events by invalidating the relevant
 * DataCache and dispatching an `entity:reload` DOM event so active
 * feature modules can refresh their UI.
 */

import {
    devicesCache, outputTargetsCache, colorStripSourcesCache,
    streamsCache, audioSourcesCache, valueSourcesCache,
    syncClocksCache, automationsCacheObj, scenePresetsCache,
    captureTemplatesCache, audioTemplatesCache, ppTemplatesCache,
    patternTemplatesCache,
} from './state.ts';

/** Maps entity_type string from the server event to its DataCache instance. */
const ENTITY_CACHE_MAP = {
    device:             devicesCache,
    output_target:      outputTargetsCache,
    color_strip_source: colorStripSourcesCache,
    picture_source:     streamsCache,
    audio_source:       audioSourcesCache,
    value_source:       valueSourcesCache,
    sync_clock:         syncClocksCache,
    automation:         automationsCacheObj,
    scene_preset:       scenePresetsCache,
    capture_template:   captureTemplatesCache,
    audio_template:     audioTemplatesCache,
    pp_template:        ppTemplatesCache,
    pattern_template:   patternTemplatesCache,
};

/** Maps entity_type to the window load function that refreshes its UI. */
const ENTITY_LOADER_MAP = {
    device:             'loadTargetsTab',
    output_target:      'loadTargetsTab',
    color_strip_source: 'loadTargetsTab',
    pattern_template:   'loadTargetsTab',
    picture_source:     'loadPictureSources',
    audio_source:       'loadPictureSources',
    value_source:       'loadPictureSources',
    sync_clock:         'loadPictureSources',
    capture_template:   'loadPictureSources',
    audio_template:     'loadPictureSources',
    pp_template:        'loadPictureSources',
    automation:         'loadAutomations',
    scene_preset:       'loadAutomations',
};

/** Debounce timers per loader function name — coalesces rapid WS events and
 *  avoids a redundant re-render when the local save handler already triggered one. */
const _loaderTimers = {};
const _LOADER_DEBOUNCE_MS = 600;

function _invalidateAndReload(entityType) {
    const cache = ENTITY_CACHE_MAP[entityType];
    if (!cache) return;

    const oldData = cache.data;
    cache.fetch({ force: true }).then((newData) => {
        // Skip UI refresh if the data didn't actually change —
        // the local save handler already refreshed the UI.
        if (oldData === newData) return;
        if (Array.isArray(oldData) && Array.isArray(newData) &&
            oldData.length === newData.length &&
            oldData.every((item, i) => {
                const other = newData[i];
                return item === other || (
                    item && other &&
                    item.id === other.id &&
                    item.updated_at === other.updated_at
                );
            })) return;

        const loader = ENTITY_LOADER_MAP[entityType];
        if (loader) {
            clearTimeout(_loaderTimers[loader]);
            _loaderTimers[loader] = setTimeout(() => {
                delete _loaderTimers[loader];
                if (typeof (window as any)[loader] === 'function') (window as any)[loader]();
            }, _LOADER_DEBOUNCE_MS);
        }
    });

    document.dispatchEvent(new CustomEvent('entity:reload', {
        detail: { entity_type: entityType },
    }));
}

function _onEntityChanged(e) {
    const { entity_type } = e.detail || {};
    if (!entity_type) return;
    _invalidateAndReload(entity_type);
}

function _onDeviceHealthChanged() {
    _invalidateAndReload('device');
}

/**
 * Register listeners for server-pushed entity events.
 * Call once during app initialization, after startEventsWS().
 */
export function startEntityEventListeners() {
    document.addEventListener('server:entity_changed', _onEntityChanged);
    document.addEventListener('server:device_health_changed', _onDeviceHealthChanged);
}
