import { __awaiter, __rest } from "tslib";
import { DefaultApiFactory } from "@qorebase/sdk";
import { tableParams } from "../../utils/tableParams";
export const transformRow = (endpoint, storageToken, view, row) => {
    const columnMap = Object.fromEntries(view.columns.map((column) => [column.name, column]) || []);
    return Object.fromEntries(Object.entries(row).map(([key, val]) => {
        var _a, _b, _c, _d;
        if (!(val && typeof val === "object" && "filename" in val))
            return [key, val];
        if (storageToken && "url" in val) {
            return [key, `${val.url}?token=${storageToken}`];
        }
        const column = columnMap[key];
        const tableName_ = (column === null || column === void 0 ? void 0 : column.type) === "lookup" &&
            ((_b = columnMap[(_a = column.definition) === null || _a === void 0 ? void 0 : _a.relation]) === null || _b === void 0 ? void 0 : _b.references)
            ? columnMap[(_c = column.definition) === null || _c === void 0 ? void 0 : _c.relation].references.targetTable
            : "query" in view && typeof view.query !== "string"
                ? view.query.table
                : view.name;
        const rowId = ((column === null || column === void 0 ? void 0 : column.type) === "lookup" &&
            row[(_d = column.definition) === null || _d === void 0 ? void 0 : _d.relation]) ||
            row.id;
        const columnName = ((column === null || column === void 0 ? void 0 : column.type) === "lookup" && column.definition.column) || key;
        return [
            key,
            `${endpoint}/v1/files/public/${tableName_}/${rowId}/${columnName}/${
            // @ts-ignore
            val.filename}`,
        ];
    }));
};
export const qoreSourceFetcher = (source, storageToken, type, view, client, options = {}) => {
    var _a, _b, _c;
    const rowId = "rowId" in source ? source.rowId : null;
    const sdk = DefaultApiFactory({
        apiKey: client.project.config.adminSecret,
        isJsonMime: (mime) => {
            const jsonMime = new RegExp("^(application/json|[^;/ \\t]+/[^;/ \\t]+[+]json)[ \\t]*(;.*)?$", "i");
            return (mime !== null &&
                (jsonMime.test(mime) ||
                    mime.toLowerCase() === "application/json-patch+json"));
        },
        accessToken: (_b = (_a = client.project.config).getToken) === null || _b === void 0 ? void 0 : _b.call(_a),
    }, client.project.config.endpoint);
    const clientTable = type === "table"
        ? client.table(source.target || null)
        : // @ts-ignore
            client.table(((_c = view === null || view === void 0 ? void 0 : view.query) === null || _c === void 0 ? void 0 : _c.table) || "");
    const clientView = type === "table"
        ? client.table(source.target || null)
        : type === "view"
            ? client.view(source.target)
            : client.insight(source.target);
    const transformRow_ = (row) => view
        ? transformRow(client.project.config.endpoint, storageToken, view, row)
        : row;
    const params = tableParams(view).map((param) => ({
        slug: param.name,
        type: param.type,
        required: true,
    })) || [];
    const inputParams = (view === null || view === void 0 ? void 0 : view.columns.map((field) => ({
        slug: field.name,
        type: field.type,
        required: true,
    }))) || [];
    const fields = (view === null || view === void 0 ? void 0 : view.columns.map((field) => ({
        id: field.name,
        display: field.name,
        type: field.type,
    })).filter((column) => {
        var _a;
        return !(type === "view" &&
            view &&
            // @ts-ignore
            !(((_a = view.query) === null || _a === void 0 ? void 0 : _a.fields) || []).includes(column.id));
    })) || [];
    const fetch = (params) => {
        const defaultRow = (source.type === "record" &&
            source.defaultRow.type === "row-id" &&
            source.defaultRow.rowId) ||
            null;
        const fetchFirstRow = source.type === "record" && source.defaultRow.type === "first-row";
        if (!(source === null || source === void 0 ? void 0 : source.target))
            return Promise.resolve({});
        switch (type) {
            case "table":
            case "view":
                return clientView
                    .readRows({
                    params: source.params,
                    condition: fetchFirstRow
                        ? undefined
                        : {
                            $and: [
                                {
                                    id: {
                                        $eq: rowId || defaultRow,
                                    },
                                },
                            ],
                        },
                    limit: 1,
                }, options)
                    .toPromise()
                    .then((data) => {
                    var _a, _b, _c, _d;
                    return (((_b = (_a = data.data) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b[0]) && transformRow_((_d = (_c = data.data) === null || _c === void 0 ? void 0 : _c.nodes) === null || _d === void 0 ? void 0 : _d[0])) ||
                        {};
                });
            case "insight":
                return clientView
                    .readRows({
                    start: params === null || params === void 0 ? void 0 : params.start,
                    end: params === null || params === void 0 ? void 0 : params.end,
                    params: source.params,
                }, options)
                    .toPromise()
                    .then((data) => { var _a, _b; return ((_b = (_a = data.data) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b[0]) || {}; });
            case "query":
                return sdk
                    .query(view.name, { params: source.params })
                    .then((data) => { var _a; return ((_a = data.data) === null || _a === void 0 ? void 0 : _a[0]) || {}; });
            default:
                return Promise.resolve({});
        }
    };
    const fetchList = (params) => {
        var _a, _b, _c;
        const sourceList = source.type === "list" || source.type === "standalone-list"
            ? source
            : source.type === "record-list" && source.sourceType === "list"
                ? Object.assign(Object.assign({}, source), { type: "list" })
                : null;
        if (!(source === null || source === void 0 ? void 0 : source.target))
            return Promise.resolve([]);
        const sourceListOpts = sourceList.type === "list"
            ? {
                limit: sourceList === null || sourceList === void 0 ? void 0 : sourceList.limit,
                offset: sourceList === null || sourceList === void 0 ? void 0 : sourceList.offset,
            }
            : {};
        switch (type) {
            case "insight":
                return clientView
                    .readRows({
                    start: (_a = params === null || params === void 0 ? void 0 : params.start) !== null && _a !== void 0 ? _a : "",
                    end: (_b = params === null || params === void 0 ? void 0 : params.end) !== null && _b !== void 0 ? _b : "",
                    params: sourceList.params,
                }, options)
                    .toPromise()
                    .then((data) => { var _a; return ((_a = data.data) === null || _a === void 0 ? void 0 : _a.nodes) || []; });
            case "table":
            case "view":
                return clientView
                    .readRows(Object.assign({ params: sourceList === null || sourceList === void 0 ? void 0 : sourceList.params, orderBy: ((_c = sourceList === null || sourceList === void 0 ? void 0 : sourceList.sorts) === null || _c === void 0 ? void 0 : _c.field)
                        ? {
                            [sourceList.sorts.field]: sourceList.sorts.type,
                        }
                        : undefined }, sourceListOpts), options)
                    .toPromise()
                    .then((data) => { var _a; return ((_a = data.data) === null || _a === void 0 ? void 0 : _a.nodes.map((row) => transformRow_(row))) || []; });
            case "query":
                return sdk
                    .query(view.name, { params: sourceList.params })
                    .then((data) => data.data);
        }
    };
    const store = (params) => __awaiter(void 0, void 0, void 0, function* () {
        var _d, _e;
        const { id } = params, params_ = __rest(params, ["id"]);
        // TODO: store for view should insert to view instead of table
        const result = yield (id
            ? clientTable.updateRow(id, params_)
            : clientTable.insertRow(params_));
        return id ? result : (_e = (_d = result.results) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e[0];
    });
    const del = (params) => __awaiter(void 0, void 0, void 0, function* () {
        const { id } = params;
        // TODO: store for view should insert to view instead of table
        yield clientTable.deleteRow(id);
    });
    return {
        type,
        params,
        inputParams,
        fields,
        fetch,
        fetchList,
        store,
        del,
    };
};
//# sourceMappingURL=qoreSourceHooks.js.map