import {defineStore, getActivePinia} from 'pinia'
import {config} from '@/config'
import {toRaw} from "vue";
import {getCsrfToken} from "@/backend.js";

export const useErrorStore = defineStore('error', {
    state() {
        return {
            errors: [],
            sendCache: [],
            autoSubmitInterval: 30000,
            autoSubmitTimer: null
        }
    },
    getters: {
        lastError: (state) => state.errors.length > 0 ? state.errors[state.errors.length - 1].error : null,
    },
    actions: {
        clearErrors() {
            this.errors = [];
            console.log("Cleared errors");
        },
        async addError(errorDto, options = {}) {
            const {request = null, store = null, global = false} = options;
            const state = this.captureStoreState(store, global);

            const error = {
                error: {
                    code: errorDto.code ?? 'Unknown error code',
                    title: errorDto.title ?? 'Unknown error',
                    message: errorDto.message ?? 'Unknown message',
                    trace: errorDto.trace ?? null,
                    traceCombined: errorDto.traceCombined ?? null,
                },
                request: request ? JSON.stringify(request) : null,
                state: state ? JSON.stringify(state) : null,
                timestamp: Date.now()
            }

            console.log(error);

            this.errors.push(error);
            this.sendCache.push(error);
            await this.transmitErrors();
        },
        async transmitErrors() {

            const params = {
                method: 'POST',
                credentials: 'include',
                headers: {
                    'Content-Type': 'application/json',
                    'X-XSRF-TOKEN': getCsrfToken()
                },
                body: JSON.stringify(toRaw(this.sendCache))
            };

            const url = `${config.backendUrl}/error/`;


            const response = await fetch(url, params
            ).catch(e => {
                this.startAutoSubmitTimer();
            });

            if (response?.ok) {
                this.stopAutoSubmitTimer()
                this.sendCache = [];
            } else {
                console.error("Error transmitting errors: " + url, params);
                console.error(response, await response?.text());
                this.startAutoSubmitTimer();
            }
        },
        startAutoSubmitTimer() {
            if (this.autoSubmitTimer) return

            this.autoSubmitTimer = setTimeout(() => {
                this.transmitErrors()
            }, this.autoSubmitInterval)
        },
        stopAutoSubmitTimer() {
            if (this.autoSubmitTimer) {
                clearTimeout(this.autoSubmitTimer)
                this.autoSubmitTimer = null
            }
        },
        captureStoreState(selectedStore = null, global = false) {
            const storeState = {}

            try {

                if (selectedStore && selectedStore.$id) {
                    storeState[selectedStore.$id] = {
                        ...toRaw(selectedStore.$state)
                    }
                }

                if (global) {
                    const pinia = this.$pinia || getActivePinia()
                    if (pinia && pinia._s) {
                        pinia._s.forEach((store, storeId) => {
                            if (storeId !== 'error' && store.$state) {
                                storeState[storeId] = {
                                    ...toRaw(store.$state)
                                }
                            }
                        })
                    }
                }
            } catch (err) {
                console.warn('Failed to capture store state:', err);
                return {};
            }

            return storeState;
        },
        async submitOnBeforeUnload() {
            if (this.sendCache.length > 0) {
                navigator.sendBeacon('/api/errors', JSON.stringify(
                    toRaw(this.sendCache)
                ))
            }
        }
    },


});

// Global Error Handler Setup
export function setupErrorBuffer() {
    const errorStore = useErrorStore()

    //Unhandled Promise Rejections
    // window.addEventListener('unhandledrejection', (event) => {

    //     const error = {
    //         code: "Unhandled rejection",
    //         title: "Frontend error",
    //         message: event.reason?.message || 'Unhandled Promise Rejection',
    //         traceCombined: event.reason?.stack,
    //     };

    //     errorStore.addError(error, {global: true}).then(r => {} );
    // })

    // // JavaScript Errors
    // window.addEventListener('error', (event) => {
    //     const error = {
    //         code: "General error",
    //         title: "Frontend error",
    //         message: event.reason?.message || 'Unhandled Promise Rejection',
    //         traceCombined: event.reason?.stack,
    //     };
    //     errorStore.addError(error, {global: true}).then(r => {} );
    // })

    window.addEventListener('beforeunload', () => {
        errorStore.submitOnBeforeUnload();
    })
}