import { FormType } from "../../Components/Forms/ModelForm";
import { APP_API_URL } from "../../Config";
import API from "../API/API";
import Navigation from "../Navigation";
import ProjectUtil from "../Project";
import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
import HTTPMethod from "../../../Types/API/HTTPMethod";
import HTTPResponse from "../../../Types/API/HTTPResponse";
import Route from "../../../Types/API/Route";
import URL from "../../../Types/API/URL";
import BadDataException from "../../../Types/Exception/BadDataException";
import JSONFunctions from "../../../Types/JSONFunctions";
export default class ModelAPI {
    static async create(data) {
        const { model, modelType, requestOptions } = data;
        return await ModelAPI.createOrUpdate({
            model,
            modelType,
            formType: FormType.Create,
            miscDataProps: {},
            requestOptions,
        });
    }
    static async update(model, modelType) {
        return await ModelAPI.createOrUpdate({
            model,
            modelType,
            formType: FormType.Update,
        });
    }
    static async updateById(args) {
        const { modelType, id, data, apiUrlOverride, requestOptions } = args;
        const model = new modelType();
        let apiUrl = apiUrlOverride || null;
        if (!apiUrl) {
            const apiPath = model.crudApiPath;
            if (!apiPath) {
                throw new BadDataException("This model does not support create or update operations.");
            }
            apiUrl = URL.fromURL(APP_API_URL).addRoute(apiPath);
        }
        apiUrl = apiUrl.addRoute(`/${id.toString()}`);
        const result = await API.fetch({
            method: HTTPMethod.PUT,
            url: apiUrl,
            data: {
                data: data,
            },
            headers: this.getCommonHeaders(requestOptions),
        });
        if (result.isSuccess()) {
            return result;
        }
        this.checkStatusCode(result);
        throw result;
    }
    static async createOrUpdate(data) {
        const { model, modelType, formType, miscDataProps, requestOptions } = data;
        let apiUrl = (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.overrideRequestUrl) || null;
        if (!apiUrl) {
            const apiPath = model.crudApiPath;
            if (!apiPath) {
                throw new BadDataException("This model does not support create or update operations.");
            }
            apiUrl = URL.fromURL(APP_API_URL).addRoute(apiPath);
        }
        const httpMethod = formType === FormType.Create ? HTTPMethod.POST : HTTPMethod.PUT;
        if (httpMethod === HTTPMethod.PUT) {
            apiUrl = apiUrl.addRoute(`/${model._id}`);
        }
        const apiResult = await API.fetch({
            method: httpMethod,
            url: apiUrl,
            data: {
                data: JSONFunctions.serialize(AnalyticsBaseModel.toJSON(model, modelType)),
                miscDataProps: miscDataProps || {},
            },
            headers: Object.assign(Object.assign({}, this.getCommonHeaders(requestOptions)), ((requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.requestHeaders) || {})),
        });
        if (apiResult.isSuccess() && apiResult instanceof HTTPResponse) {
            const result = apiResult;
            result.data = AnalyticsBaseModel.fromJSON(result.data, modelType);
            return result;
        }
        this.checkStatusCode(apiResult);
        throw apiResult;
    }
    static async aggregate(data) {
        const { modelType, aggregateBy, requestOptions } = data;
        const model = new modelType();
        const apiPath = model.crudApiPath;
        if (!apiPath) {
            throw new BadDataException("This model does not support aggregate operations.");
        }
        let apiUrl = URL.fromURL(APP_API_URL)
            .addRoute(apiPath)
            .addRoute("/aggregate");
        if (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.overrideRequestUrl) {
            apiUrl = requestOptions.overrideRequestUrl;
        }
        if (!apiUrl) {
            throw new BadDataException("This model does not support list operations.");
        }
        const headers = this.getCommonHeaders(requestOptions);
        const result = await API.fetch({
            method: HTTPMethod.POST,
            url: apiUrl,
            data: {
                aggregateBy: JSONFunctions.serialize(aggregateBy),
            },
            headers,
        });
        if (result.isSuccess()) {
            const aggregatedResult = result.data;
            return aggregatedResult;
        }
        this.checkStatusCode(result);
        throw result;
    }
    static async getList(data) {
        const { modelType, query, limit, skip, select, sort, requestOptions, groupBy, } = data;
        const model = new modelType();
        const apiPath = model.crudApiPath;
        if (!apiPath) {
            throw new BadDataException("This model does not support list operations.");
        }
        let apiUrl = URL.fromURL(APP_API_URL)
            .addRoute(apiPath)
            .addRoute("/get-list");
        if (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.overrideRequestUrl) {
            apiUrl = requestOptions.overrideRequestUrl;
        }
        if (!apiUrl) {
            throw new BadDataException("This model does not support list operations.");
        }
        const headers = this.getCommonHeaders(requestOptions);
        const result = await API.fetch({
            method: HTTPMethod.POST,
            url: apiUrl,
            data: {
                query: JSONFunctions.serialize(query),
                select: JSONFunctions.serialize(select),
                sort: JSONFunctions.serialize(sort),
                groupBy: JSONFunctions.serialize(groupBy),
            },
            headers,
            params: {
                limit: limit.toString(),
                skip: skip.toString(),
            },
        });
        if (result.isSuccess()) {
            const list = AnalyticsBaseModel.fromJSONArray(result.data, modelType);
            return {
                data: list,
                count: result.count,
                skip: result.skip,
                limit: result.limit,
                hasMore: result.hasMore,
            };
        }
        this.checkStatusCode(result);
        throw result;
    }
    static async count(modelType, query, requestOptions) {
        const model = new modelType();
        const apiPath = model.crudApiPath;
        if (!apiPath) {
            throw new BadDataException("This model does not support list operations.");
        }
        let apiUrl = URL.fromURL(APP_API_URL)
            .addRoute(apiPath)
            .addRoute("/count");
        if (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.overrideRequestUrl) {
            apiUrl = requestOptions.overrideRequestUrl;
        }
        if (!apiUrl) {
            throw new BadDataException("This model does not support count operations.");
        }
        const headers = this.getCommonHeaders(requestOptions);
        const result = await API.fetch({
            method: HTTPMethod.POST,
            url: apiUrl,
            data: {
                query: JSONFunctions.serialize(query),
            },
            headers,
        });
        if (result.isSuccess()) {
            const count = result.data["count"];
            return count;
        }
        this.checkStatusCode(result);
        throw result;
    }
    static getCommonHeaders(requestOptions) {
        let headers = {};
        if (!requestOptions || Object.keys(requestOptions).length === 0) {
            const project = ProjectUtil.getCurrentProject();
            if (project && project.id) {
                headers["tenantid"] = project.id.toString();
            }
        }
        // add SSO headers.
        headers = Object.assign({}, headers);
        return headers;
    }
    static async getItem(data) {
        const { modelType, id, select, requestOptions } = data;
        const apiPath = new modelType().crudApiPath;
        if (!apiPath) {
            throw new BadDataException("This model does not support get operations.");
        }
        let apiUrl = URL.fromURL(APP_API_URL)
            .addRoute(apiPath)
            .addRoute("/" + id.toString())
            .addRoute("/get-item");
        if (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.overrideRequestUrl) {
            apiUrl = requestOptions.overrideRequestUrl;
        }
        if (!apiUrl) {
            throw new BadDataException("This model does not support get operations.");
        }
        return this.post(modelType, apiUrl, select, requestOptions);
    }
    static async post(modelType, apiUrl, select, requestOptions) {
        const result = await API.fetch({
            method: HTTPMethod.POST,
            url: apiUrl,
            data: {
                select: JSONFunctions.serialize(select) || {},
            },
            headers: this.getCommonHeaders(requestOptions),
        });
        if (result.isSuccess()) {
            return AnalyticsBaseModel.fromJSON(result.data, modelType);
        }
        this.checkStatusCode(result);
        throw result;
    }
    static async deleteItem(data) {
        const { modelType, id, requestOptions } = data;
        const apiPath = new modelType().crudApiPath;
        if (!apiPath) {
            throw new BadDataException("This model does not support delete operations.");
        }
        const apiUrl = URL.fromURL(APP_API_URL)
            .addRoute(apiPath)
            .addRoute("/" + id.toString());
        if (!apiUrl) {
            throw new BadDataException("This model does not support delete operations.");
        }
        const result = await API.fetch({
            method: HTTPMethod.DELETE,
            url: apiUrl,
            headers: this.getCommonHeaders(requestOptions),
        });
        if (result.isSuccess()) {
            return;
        }
        this.checkStatusCode(result);
        throw result;
    }
    static checkStatusCode(result) {
        if (result.statusCode === 406) {
            const project = ProjectUtil.getCurrentProject();
            if (project && project.id) {
                Navigation.navigate(new Route(`/dashboard/${project._id}/sso`));
            }
        }
    }
}
//# sourceMappingURL=AnalyticsModelAPI.js.map