import { executeServerJob } from "./executor.js";
import { JOB_DONE_EVENT_PREFIX } from "../../types/events/jobDone.js";
import { jobDelay } from "../job/delay.js";

import type { JobDoneEvent } from "../../types/events/jobDone.js";
import type { Job } from "../../types/job.js";
import type { getGlobalQueue } from "../global.js";
import type { Task } from "../queueClass.js";

/**
 * Memorize all executed server jobs to avoid multiple executions.
 * Why: We have created a task for each job, but on server side we
 * are executing jobs iteratively until max execution time exceeded.
 *
 * Simply said: One network request could potentially execute
 * multiple jobs.
 */
const SUCCESSFUL_SERVER_JOBS: number[] = [];

/**
 * Convert a server job to promise.
 *
 * @param tryIds All the Job IDs which should be also be tried with this single request
 */
function convertServerJobToPromise(queue: ReturnType<typeof getGlobalQueue>, job: Job, tryIds: number[]) {
    const { id, type } = job;

    const fn: Task = async () => {
        const dispatchDoneEvent = (success: boolean) =>
            document.dispatchEvent(
                new CustomEvent<JobDoneEvent>(`${JOB_DONE_EVENT_PREFIX}${type}`, {
                    detail: {
                        job,
                        success,
                    },
                }),
            );

        if (SUCCESSFUL_SERVER_JOBS.indexOf(id) > -1) {
            // Job already executed, skip this!
            dispatchDoneEvent(true);
            return;
        }

        try {
            const { done } = await executeServerJob(job, tryIds);
            SUCCESSFUL_SERVER_JOBS.push(...done.map(({ id }) => id));

            dispatchDoneEvent(SUCCESSFUL_SERVER_JOBS.indexOf(id) > -1);
        } catch (e) {
            // Something went wrong between request and WP REST API - we pause the queue here cause
            // we wait for the next refresh of the page - the REST API response is always valid and
            // does not throw any error
            queue.handler.pause();
        }
    };

    const delay: Task = () => (SUCCESSFUL_SERVER_JOBS.indexOf(id) > -1 ? Promise.resolve() : jobDelay(job));

    return [fn, delay];
}

export { convertServerJobToPromise };
