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 { DeepClient } from '../client.js';
import { handleOperation, handleSelectorOperation, } from './links.js';
import { boolExpToSQL } from '../bool_exp_to_sql.js';
const SCHEMA = 'public';
const debug = Debug('deeplinks:eh:values');
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,
});
const portHash = {};
const containerHash = {};
export default (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
    try {
        const event = (_a = req === null || req === void 0 ? void 0 : req.body) === null || _a === void 0 ? void 0 : _a.event;
        const triggeredByLinkId = parseInt(event.session_variables["x-hasura-user-id"]);
        const operation = event === null || event === void 0 ? void 0 : event.op;
        if (operation === 'INSERT' || operation === 'UPDATE' || operation === 'DELETE') {
            let linkId;
            let linkRow;
            let oldValueRow;
            let newValueRow;
            let newRow;
            let oldRow;
            try {
                oldValueRow = (_b = event === null || event === void 0 ? void 0 : event.data) === null || _b === void 0 ? void 0 : _b.old;
                newValueRow = (_c = event === null || event === void 0 ? void 0 : event.data) === null || _c === void 0 ? void 0 : _c.new;
                linkId = (_d = newValueRow === null || newValueRow === void 0 ? void 0 : newValueRow.link_id) !== null && _d !== void 0 ? _d : oldValueRow === null || oldValueRow === void 0 ? void 0 : oldValueRow.link_id;
                linkRow = (_f = (_e = (yield deep.select({
                    id: { _eq: linkId },
                }, {
                    returning: `id from_id type_id to_id`,
                }))) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f[0];
                const handleUpdateTypeId = yield deep.id('@deep-foundation/core', 'HandleUpdate');
                const queryResult = (_j = (_h = (_g = (yield client.query({
                    query: gql `
            query {
              promise_links(where: {
                handle_operation_type_id: { _eq: ${handleUpdateTypeId} },
                old_link_id: {_eq: ${linkId}},
                new_link_id: {_eq: ${linkId}},
                values_operation: { _eq: "${operation}" }
              }) {
                id
                promise_id
                old_link_id
                old_link_type_id
                old_link_from_id
                old_link_to_id
                new_link_id
                new_link_type_id
                new_link_from_id
                new_link_to_id
                handle_operation_id
              }
            }
          `,
                }))) === null || _g === void 0 ? void 0 : _g.data) === null || _h === void 0 ? void 0 : _h.promise_links) === null || _j === void 0 ? void 0 : _j[0];
                const oldLinkRow = {
                    id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.old_link_id,
                    type_id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.old_link_type_id,
                    from_id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.old_link_from_id,
                    to_id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.old_link_to_id,
                };
                const newLinkRow = {
                    id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.new_link_id,
                    type_id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.new_link_type_id,
                    from_id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.new_link_from_id,
                    to_id: queryResult === null || queryResult === void 0 ? void 0 : queryResult.new_link_to_id,
                };
                log(`oldLinkRow: ${JSON.stringify(oldLinkRow)}`);
                log(`newLinkRow: ${JSON.stringify(newLinkRow)}`);
                oldRow = Object.assign(Object.assign({}, linkRow), { value: oldValueRow });
                newRow = Object.assign(Object.assign({}, linkRow), { value: newValueRow });
                if (!linkRow) {
                    if (newValueRow === null || newValueRow === void 0 ? void 0 : newValueRow.link_id) {
                        throw new Error('Value insert is handled before the link is added.');
                    }
                    else {
                        throw new Error('Value deletion is handled after its link is deleted.');
                    }
                }
                log('operation', operation);
                log('linkId', linkId);
                log('linkRow', linkRow);
                log('oldValueRow', oldValueRow);
                log('newValueRow', newValueRow);
                log('newRow', newRow);
                log('oldRow', oldRow);
                if (oldValueRow && !newValueRow) {
                    yield deep.delete({
                        link_id: { _eq: oldValueRow.link_id },
                    }, { table: 'bool_exp' });
                }
                if (newValueRow && newRow.type_id === (yield deep.id('@deep-foundation/core', 'Query'))) {
                    yield boolExpToSQL(newRow.id, (_k = newRow === null || newRow === void 0 ? void 0 : newRow.value) === null || _k === void 0 ? void 0 : _k.value);
                }
                yield handleOperation('Update', triggeredByLinkId, oldRow, newRow, operation);
                yield handleSelectorOperation('Update', triggeredByLinkId, oldRow, newRow, operation);
                return res.status(200).json({});
            }
            catch (e) {
                log('operation', operation);
                log('linkId', linkId);
                log('linkRow', linkRow);
                log('oldValueRow', oldValueRow);
                log('newValueRow', newValueRow);
                log('newRow', newRow);
                log('oldRow', oldRow);
                error('Error', e);
                throw e;
            }
        }
        return res.status(500).json({ error: 'operation can be only INSERT or UPDATE' });
    }
    catch (e) {
        return res.status(500).json({ error: e.toString() });
    }
});
//# sourceMappingURL=values.js.map