var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import Debug from 'debug';
import { generateApolloClient } from '@deep-foundation/hasura/client.js';
import { HasuraApi } from '@deep-foundation/hasura/api.js';
import { gql } from '@apollo/client/index.js';
import { serializeError } from 'serialize-error';
import { findPromiseLink } from '../promise.js';
import { DeepClient } from '../client.js';
import { useRunner, processPromises } from './links.js';
const SCHEMA = 'public';
const deeplinksUrl = process.env.NEXT_PUBLIC_DEEPLINKS_URL;
const debug = Debug('deeplinks:eh:scheduler');
const log = debug.extend('log');
const error = debug.extend('error');
export const api = new HasuraApi({
    path: process.env.DEEPLINKS_HASURA_PATH,
    ssl: !!+process.env.DEEPLINKS_HASURA_SSL,
    secret: process.env.DEEPLINKS_HASURA_SECRET,
});
const client = generateApolloClient({
    path: `${process.env.DEEPLINKS_HASURA_PATH}/v1/graphql`,
    ssl: !!+process.env.DEEPLINKS_HASURA_SSL,
    secret: process.env.DEEPLINKS_HASURA_SECRET,
});
const deep = new DeepClient({
    apolloClient: client,
});
export const insertPromise = (scheduleId) => __awaiter(void 0, void 0, void 0, function* () {
    const promiseTypeId = deep.idLocal('@deep-foundation/core', 'Promise');
    const thenTypeId = deep.idLocal('@deep-foundation/core', 'Then');
    const promise = (yield deep.insert({
        type_id: promiseTypeId,
    }, { name: 'IMPORT_HANDLER_JS_FILE' })).data[0];
    const then = (yield deep.insert({
        from_id: scheduleId,
        type_id: thenTypeId,
        to_id: promise === null || promise === void 0 ? void 0 : promise.id,
    }, { name: 'IMPORT_HANDLER' })).data[0];
    return {
        id: promise === null || promise === void 0 ? void 0 : promise.id,
        thenId: then === null || then === void 0 ? void 0 : then.id,
    };
});
export function handleScheduleMomemt(moment) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
    return __awaiter(this, void 0, void 0, function* () {
        const scheduleId = moment.payload.scheduleId;
        const resolvedTypeId = deep.idLocal('@deep-foundation/core', 'Resolved');
        const rejectedTypeId = deep.idLocal('@deep-foundation/core', 'Rejected');
        const promise = yield findPromiseLink({
            id: scheduleId, client: deep.apolloClient,
            Then: deep.idLocal('@deep-foundation/core', 'Then'),
            Promise: deep.idLocal('@deep-foundation/core', 'Promise'),
            Resolved: resolvedTypeId,
            Rejected: rejectedTypeId,
            Results: false,
        });
        log('promise: ', promise);
        if (promise) {
            const handlerTypeId = deep.idLocal('@deep-foundation/core', 'Handler');
            const handleOperationTypeId = deep.idLocal('@deep-foundation/core', 'HandleSchedule');
            const queryString = `query SELECT_CODE($scheduleId: bigint) { links(where: {
            type_id: { _eq: ${deep.idLocal('@deep-foundation/core', 'SyncTextFile')} },
            in: {
              from_id: { _eq: ${deep.idLocal('@deep-foundation/core', 'dockerSupportsJs')} },
              type_id: { _eq: ${handlerTypeId} },
              in: {
                from_id: { _eq: $scheduleId },
                type_id: { _eq: ${handleOperationTypeId} },
              }
            }
          }) {
            id
            value
            in(where: { type_id: { _eq: ${handlerTypeId} } }) {
              id
              in(where: { type_id: { _eq: ${handleOperationTypeId} } }) {
                id
              }
              support: from {
                id
                isolation: from {
                  id
                  image: value
                }
              }
            }
          } }`;
            const query = gql `${queryString}`;
            const variables = {
                scheduleId
            };
            const handlersResult = yield client.query({ query, variables });
            const promises = [];
            const handleOperationsIds = [];
            const handlersWithCode = (_a = handlersResult === null || handlersResult === void 0 ? void 0 : handlersResult.data) === null || _a === void 0 ? void 0 : _a.links;
            log('handlersWithCode.length', handlersWithCode === null || handlersWithCode === void 0 ? void 0 : handlersWithCode.length);
            if ((handlersWithCode === null || handlersWithCode === void 0 ? void 0 : handlersWithCode.length) > 0) {
                log("handlersWithCode: ", JSON.stringify(handlersWithCode, null, 2));
                log(handlersWithCode === null || handlersWithCode === void 0 ? void 0 : handlersWithCode.length);
                for (const handlerWithCode of handlersWithCode) {
                    const code = (_b = handlerWithCode === null || handlerWithCode === void 0 ? void 0 : handlerWithCode.value) === null || _b === void 0 ? void 0 : _b.value;
                    const isolationProviderImageName = (_g = (_f = (_e = (_d = (_c = handlerWithCode === null || handlerWithCode === void 0 ? void 0 : handlerWithCode.in) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.support) === null || _e === void 0 ? void 0 : _e.isolation) === null || _f === void 0 ? void 0 : _f.image) === null || _g === void 0 ? void 0 : _g.value;
                    const handlerId = (_j = (_h = handlerWithCode === null || handlerWithCode === void 0 ? void 0 : handlerWithCode.in) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.id;
                    const handleOperationId = (_m = (_l = (_k = handlerWithCode === null || handlerWithCode === void 0 ? void 0 : handlerWithCode.in) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.in) === null || _m === void 0 ? void 0 : _m[0].id;
                    if (code && isolationProviderImageName && handlerId && handleOperationId) {
                        try {
                            promises.push(() => useRunner({ code, handlerId, isolationProviderImageName, data: { moment, promiseId: promise.id, deeplinksUrl } }));
                            handleOperationsIds.push(handleOperationId);
                        }
                        catch (e) {
                            const serializedError = serializeError(e);
                            error('error', JSON.stringify(serializedError, null, 2));
                        }
                    }
                    else {
                        promises.push(() => __awaiter(this, void 0, void 0, function* () { return Promise.reject(new Error('Code of a handler is not loaded.')); }));
                        handleOperationsIds.push(handleOperationId);
                    }
                }
                const promiseResultTypeId = deep.idLocal('@deep-foundation/core', 'PromiseResult');
                const promiseReasonTypeId = deep.idLocal('@deep-foundation/core', 'PromiseReason');
                yield insertPromise(scheduleId);
                yield processPromises(promises, handleOperationsIds, promise.id, promiseResultTypeId, promiseReasonTypeId, resolvedTypeId, rejectedTypeId, log);
            }
        }
    });
}
export default (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    try {
        const event = req === null || req === void 0 ? void 0 : req.body;
        const operation = event === null || event === void 0 ? void 0 : event.op;
        log(`event`, event);
        try {
            yield handleScheduleMomemt(event);
            return res.status(200).json({});
        }
        catch (e) {
            const serializedError = serializeError(e);
            error('error', JSON.stringify(serializedError, null, 2));
            throw e;
        }
        return res.status(500).json({ error: 'notexplained' });
    }
    catch (e) {
        const serializedError = serializeError(e);
        return res.status(500).json({ error: serializedError });
    }
});
//# sourceMappingURL=scheduler.js.map