import { defineStore } from 'pinia';
import { useCrudStore } from './crud';

export interface PollingJob {
    jobId: string;
    name: string;
    pollingAttemptsCount: number;
    isPolling: boolean;
    isFetchingResult: boolean;
    maxAttempts: number;
    intervalId: any;
    isLastAttempt?: boolean;
}

export const useJobPollingStore = defineStore('jobPolling', {
    state: () => ({
        pollingJobResults: [] as PollingJob[]
    }),

    getters: {
        getJob: (state) => (name: string) => {
            return state.pollingJobResults.find(item => item.name === name);
        },
        getJobAttemptCount: (state) => (name: string) => {
            const job = state.pollingJobResults.find(item => item.name === name);
            return job ? job.pollingAttemptsCount : 0;
        }
    },

    actions: {
        submitJobRequest({ url, name }: { url: string; name: string }) {
            const crudStore = useCrudStore();
            crudStore.crudRequest({
                endpoint: url,
                method: 'get'
            }).then(response => {
                if (response.ok) {
                    response.json().then(data => {
                        const jobId = data.payload.data.job_id;
                        if (jobId) {
                            this.startPolling({ jobId, name, pollingAttemptsCount: 0 });
                        }
                    });
                }
            });
        },

        stopPollingJobResultByJobId(jobId: string) {
            const index = this.pollingJobResults.findIndex(s => s.jobId === jobId);
            if (index !== -1) {
                clearInterval(this.pollingJobResults[index].intervalId);
                this.pollingJobResults.splice(index, 1);
            }
        },

        stopPollingJobResultByName(name: string) {
            const index = this.pollingJobResults.findIndex(s => s.name === name);
            if (index !== -1) {
                clearInterval(this.pollingJobResults[index].intervalId);
                this.pollingJobResults.splice(index, 1);
            }
        },

        startPolling({ jobId, name, pollingAttemptsCount, maxAttempts = 8 }: { jobId: string; name: string; pollingAttemptsCount: number; maxAttempts?: number }) {
            const interval = 10000;

            const pollJobResult = () => {
                const index = this.pollingJobResults.findIndex(s => s.jobId === jobId);
                if (index !== -1) {
                    let currentJob = this.pollingJobResults[index];
                    if (currentJob.isPolling || currentJob.isFetchingResult) {
                        return;
                    }

                    let newAttemptsCount = currentJob.pollingAttemptsCount + 1;

                    if (newAttemptsCount === 1) {
                        // Restart with shorter interval if needed (though original code was a bit redundant here)
                        this.stopPollingJobResultByJobId(jobId);
                        this.addPollingJob({ jobId, name, pollingAttemptsCount: newAttemptsCount, isPolling: false, isFetchingResult: false, maxAttempts, pollJobResult, interval: 5000 });
                        return;
                    }

                    if (newAttemptsCount > maxAttempts) {
                        this.stopPollingJobResultByJobId(jobId);
                        return;
                    }

                    this.updatePollingJobResult({
                        jobId,
                        pollingAttemptsCount: newAttemptsCount,
                        isPolling: true,
                        isFetchingResult: false,
                        isLastAttempt: newAttemptsCount === maxAttempts
                    });
                } else {
                    return;
                }
            };

            this.addPollingJob({ jobId, name, pollingAttemptsCount, isPolling: false, isFetchingResult: false, maxAttempts, pollJobResult, interval });
        },

        addPollingJob({ jobId, name, pollingAttemptsCount, isPolling, isFetchingResult, maxAttempts, pollJobResult, interval }: any) {
            const intervalId = setInterval(() => {
                if (pollJobResult) {
                    pollJobResult();
                }
            }, interval);

            this.pollingJobResults.push({ jobId, name, pollingAttemptsCount, isPolling, isFetchingResult, maxAttempts, intervalId });
        },

        updatePollingJobResult({ jobId, pollingAttemptsCount, isPolling, isFetchingResult, isLastAttempt }: Partial<PollingJob>) {
            const index = this.pollingJobResults.findIndex(s => s.jobId === jobId);
            if (index !== -1) {
                const job = this.pollingJobResults[index];
                this.pollingJobResults[index] = {
                    ...job,
                    pollingAttemptsCount: pollingAttemptsCount !== undefined ? pollingAttemptsCount : job.pollingAttemptsCount,
                    isPolling: isPolling !== undefined ? isPolling : job.isPolling,
                    isFetchingResult: isFetchingResult !== undefined ? isFetchingResult : job.isFetchingResult,
                    isLastAttempt: isLastAttempt !== undefined ? isLastAttempt : job.isLastAttempt
                };
            }
        },

        updatePollingJobResultByJobId({ jobId, isPolling, isFetchingResult }: { jobId: string; isPolling: boolean; isFetchingResult: boolean }) {
            this.updatePollingJobResult({ jobId, isPolling, isFetchingResult });
        }
    }
});
