const DEBOUNCE_MS = 150;

const DEFAULT_PAGINATION = () => ({
    top_links: { page: 1 },
    recent_clicks: { page: 1 },
    geo: { tab: 'countries', page: 1 },
    referrers: { tab: 'channels', page: 1 },
});

const DEFAULT_FILTERS = () => ({
    preset: '7',
    start_date: null,
    end_date: null,
    since_start: false,
});

export default class InsightsStore {
    constructor() {
        this.filters = DEFAULT_FILTERS();
        this.pagination = DEFAULT_PAGINATION();
        this.snapshot = null;
        this.listeners = [];
        this.loading = false;
        this.debounceTimer = null;
        this.pendingRequest = null;
    }

    subscribe(callback) {
        this.listeners.push(callback);
        if (this.snapshot) {
            callback(this.snapshot, this.loading);
        }
    }

    notify() {
        this.listeners.forEach((callback) => {
            callback(this.snapshot, this.loading);
        });
    }

    setPeriod({ preset, formattedStartDate, formattedEndDate }) {
        this.filters.since_start = preset === 'since_start';
        this.filters.preset = preset;

        if (preset === 'since_start') {
            this.filters.start_date = null;
            this.filters.end_date = null;
        } else {
            this.filters.start_date = formattedStartDate || null;
            this.filters.end_date = formattedEndDate || null;
        }

        this.resetPagination();
        this.scheduleLoadAll();
    }

    setFilter(key, value) {
        if (!(key in this.filters)) {
            return;
        }
        this.filters[key] = value || null;
        this.resetPagination();
        this.scheduleLoadAll();
    }

    resetPagination() {
        const geoTab = this.pagination.geo?.tab || 'countries';
        const referrersTab = this.pagination.referrers?.tab || 'channels';
        this.pagination = DEFAULT_PAGINATION();
        this.pagination.geo.tab = geoTab;
        this.pagination.referrers.tab = referrersTab;
    }

    scheduleLoadAll() {
        clearTimeout(this.debounceTimer);
        this.debounceTimer = setTimeout(() => this.loadAll(), DEBOUNCE_MS);
    }

    loadAll() {
        return this.fetch('all', this.pagination);
    }

    loadWidgets(widgetKeys, paginationOverrides = {}) {
        const pagination = {
            ...this.pagination,
            ...paginationOverrides,
        };
        this.pagination = pagination;
        const widgets = Array.isArray(widgetKeys) ? widgetKeys : [widgetKeys];
        return this.fetch(widgets, pagination);
    }

    fetch(widgets, pagination) {
        if (this.pendingRequest && this.pendingRequest.readyState !== 4) {
            this.pendingRequest.abort();
        }

        this.loading = true;
        this.notify();

        const isFullLoad = widgets === 'all';

        const filtersPayload = {
            ...this.filters,
            since_start: this.filters.since_start ? 1 : 0,
        };

        this.pendingRequest = jQuery.ajax({
            url: linkcentral_admin.ajax_url,
            type: 'POST',
            dataType: 'json',
            data: {
                action: 'linkcentral_get_insights_snapshot',
                nonce: linkcentral_admin.nonce,
                widgets: isFullLoad ? 'all' : widgets,
                filters: filtersPayload,
                pagination,
            },
        });

        return this.pendingRequest
            .done((response) => {
                if (!response || !response.success) {
                    return;
                }

                if (isFullLoad) {
                    this.snapshot = response.data;
                } else {
                    if (!this.snapshot) {
                        this.snapshot = { context: response.data.context, widgets: {} };
                    }
                    if (response.data.context) {
                        this.snapshot.context = response.data.context;
                    }
                    const incoming = response.data.widgets;
                    if (incoming.geo && this.snapshot.widgets.geo) {
                        incoming.geo = { ...this.snapshot.widgets.geo, ...incoming.geo };
                    }
                    if (incoming.referrers && this.snapshot.widgets.referrers) {
                        incoming.referrers = { ...this.snapshot.widgets.referrers, ...incoming.referrers };
                    }
                    this.snapshot.widgets = {
                        ...this.snapshot.widgets,
                        ...incoming,
                    };
                }
            })
            .fail((jqXHR, textStatus) => {
                if (textStatus !== 'abort') {
                    console.error('Insights snapshot request failed:', textStatus);
                }
            })
            .always(() => {
                this.loading = false;
                this.notify();
            });
    }

    getSnapshot() {
        return this.snapshot;
    }

    isLoading() {
        return this.loading;
    }
}
