import { OpenAPIRegistry, OpenApiGeneratorV3, } from "@asteasolutions/zod-to-openapi";
import Models from "../../Models/DatabaseModels/Index";
import AnalyticsModels from "../../Models/AnalyticsModels/Index";
import { ModelSchema } from "../../Utils/Schema/ModelSchema";
import { AnalyticsModelSchema, } from "../../Utils/Schema/AnalyticsModelSchema";
import LocalCache from "../Infrastructure/LocalCache";
import { Host, HttpProtocol } from "../EnvironmentConfig";
import Permission from "../../Types/Permission";
export default class OpenAPIUtil {
    /**
     * Helper method to check if permissions should exclude API generation.
     * Returns true if:
     * 1. The permissions array is empty or undefined, OR
     * 2. The permissions array contains Permission.Public or Permission.CurrentUser
     */
    static shouldExcludeApiForPermissions(permissions) {
        if (!permissions || permissions.length === 0) {
            return true;
        }
        return (permissions.length > 0 &&
            permissions.every((permission) => {
                return (permission === Permission.Public ||
                    permission === Permission.CurrentUser);
            }));
    }
    static generateOpenAPISpec() {
        // check if the cache is already in LocalCache
        const cachedSpec = LocalCache.getJSON("openapi", "spec");
        if (cachedSpec) {
            return cachedSpec;
        }
        const registry = new OpenAPIRegistry();
        const tags = [];
        // Register schemas and paths for all models
        for (const ModelClass of Models) {
            const model = new ModelClass();
            const modelName = model.tableName;
            if (!modelName) {
                continue;
            }
            // check if enable documentation is enabled
            if (!model.enableDocumentation) {
                continue;
            }
            if (!model.crudApiPath) {
                continue;
            }
            // Add tag for this model
            const singularModelName = model.singularName || modelName;
            tags.push({
                name: singularModelName,
                description: model.tableDescription || `API endpoints for ${singularModelName}`,
            });
            // register the model schema
            OpenAPIUtil.registerModelSchemas(registry, model);
            this.generateListApiSpec({
                modelType: ModelClass,
                registry,
            });
            this.generateCountApiSpec({
                modelType: ModelClass,
                registry,
            });
            this.generateCreateApiSpec({
                modelType: ModelClass,
                registry,
            });
            this.generateGetApiSpec({
                modelType: ModelClass,
                registry,
            });
            this.generateUpdateApiSpec({
                modelType: ModelClass,
                registry,
            });
            this.generateDeleteApiSpec({
                modelType: ModelClass,
                registry,
            });
        }
        // Register schemas and paths for all Analytics models
        for (const AnalyticsModelClass of AnalyticsModels) {
            const analyticsModel = new AnalyticsModelClass();
            const modelName = analyticsModel.tableName;
            if (!modelName) {
                continue;
            }
            if (!analyticsModel.crudApiPath) {
                continue;
            }
            // Add tag for this model
            const singularModelName = analyticsModel.singularName || modelName;
            tags.push({
                name: singularModelName,
                description: `API endpoints for ${singularModelName}`,
            });
            // register the analytics model schema
            OpenAPIUtil.registerAnalyticsModelSchemas(registry, analyticsModel);
            this.generateAnalyticsListApiSpec({
                modelType: AnalyticsModelClass,
                registry,
            });
            this.generateAnalyticsCountApiSpec({
                modelType: AnalyticsModelClass,
                registry,
            });
            this.generateAnalyticsCreateApiSpec({
                modelType: AnalyticsModelClass,
                registry,
            });
            this.generateAnalyticsGetApiSpec({
                modelType: AnalyticsModelClass,
                registry,
            });
            this.generateAnalyticsUpdateApiSpec({
                modelType: AnalyticsModelClass,
                registry,
            });
            this.generateAnalyticsDeleteApiSpec({
                modelType: AnalyticsModelClass,
                registry,
            });
        }
        const generator = new OpenApiGeneratorV3(registry.definitions);
        const spec = generator.generateDocument({
            openapi: "3.0.0",
            info: {
                title: "OneUptime OpenAPI Specification",
                version: "1.0.0",
                description: "OpenAPI specification for OneUptime. This document describes the API endpoints, request and response formats, and other details necessary for developers to interact with the OneUptime API.",
            },
            servers: [
                {
                    url: `${HttpProtocol.toString()}${Host.toString()}/api`,
                    description: "API Server",
                },
            ],
            tags: tags.sort((a, b) => {
                return a.name.localeCompare(b.name);
            }),
        });
        // Add security schemes and global security requirement
        if (!spec["components"]) {
            spec["components"] = {};
        }
        spec["components"]["securitySchemes"] = {
            ApiKey: {
                type: "apiKey",
                in: "header",
                name: "APIKey",
                description: "API key for authentication. Required for all API requests.",
            },
        };
        spec["security"] = [
            {
                ApiKey: [],
            },
        ];
        LocalCache.setJSON("openapi", "spec", spec);
        return spec;
    }
    static generateListApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownModel";
        const singularModelName = model.singularName || tableName;
        // Use schema names that are already registered
        const querySchemaName = `${tableName}QuerySchema`;
        const selectSchemaName = `${tableName}SelectSchema`;
        const sortSchemaName = `${tableName}SortSchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}/get-list`,
            operationId: `list${tableName}`,
            summary: `List ${singularModelName}`,
            description: `Endpoint to list all ${singularModelName} items`,
            tags: [singularModelName],
            parameters: [...OpenAPIUtil.getDefaultApiHeaders()],
            requestBody: {
                required: false,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                query: { $ref: `#/components/schemas/${querySchemaName}` },
                                select: { $ref: `#/components/schemas/${selectSchemaName}` },
                                sort: { $ref: `#/components/schemas/${sortSchemaName}` },
                                limit: {
                                    type: "number",
                                    description: "Maximum number of items to return. Defaults to 10.",
                                    default: 10,
                                    minimum: 1,
                                },
                                skip: {
                                    type: "number",
                                    description: "Number of items to skip for pagination. Defaults to 0.",
                                    default: 0,
                                    minimum: 0,
                                },
                            },
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Successful response",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        type: "array",
                                        items: {
                                            $ref: `#/components/schemas/${tableName}`,
                                        },
                                    },
                                    count: { type: "number" },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateCountApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownModel";
        const singularModelName = model.singularName || tableName;
        // Use schema name that is already registered
        const querySchemaName = `${tableName}QuerySchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}/count`,
            operationId: `count${tableName}`,
            summary: `Count ${singularModelName}`,
            description: `Endpoint to count ${singularModelName} items`,
            tags: [singularModelName],
            parameters: [...OpenAPIUtil.getDefaultApiHeaders()],
            requestBody: {
                required: false,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                query: { $ref: `#/components/schemas/${querySchemaName}` },
                            },
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Successful response",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    count: { type: "number" },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateCreateApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating create API if model has no create permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.createRecordPermissions)) {
            return;
        }
        // Use schema names that are already registered
        const createSchemaName = `${tableName}CreateSchema`;
        const readSchemaName = `${tableName}ReadSchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}`,
            operationId: `create${tableName}`,
            summary: `Create ${singularModelName}`,
            description: `Endpoint to create a new ${singularModelName}`,
            tags: [singularModelName],
            requestBody: {
                required: true,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                data: {
                                    $ref: `#/components/schemas/${createSchemaName}`,
                                },
                            },
                            required: ["data"],
                        },
                    },
                },
            },
            responses: Object.assign({ "201": {
                    description: "Created successfully",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        $ref: `#/components/schemas/${readSchemaName}`,
                                    },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static getGenericStatusResponseSchema() {
        return {
            "400": {
                description: "Bad request. This response indicates that the request was malformed or contained invalid data.",
            },
            "401": {
                description: "Unauthorized. This response indicates that the request requires user authentication.",
            },
            "402": {
                description: "Payment Required. This response indicates that the request requires payment or a valid subscription.",
            },
            "403": {
                description: "Forbidden. This response indicates that the server understood the request, but refuses to authorize it.",
            },
            "408": {
                description: "Request Timeout. This response indicates that the server timed out waiting for the request.",
            },
            "405": {
                description: "Project not found. This response indicates that the requested project does not exist or is not accessible.",
            },
            "415": {
                description: "Unable to reach server. This response indicates that the server is currently unreachable or down.",
            },
            "422": {
                description: "Not authorized. This response indicates that the user does not have permission to access the requested resource.",
            },
            "500": {
                description: "Internal Server Error. This response indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.",
            },
        };
    }
    static generateGetApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating get API if model has no read permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.readRecordPermissions)) {
            return;
        }
        // Use schema name that is already registered
        const selectSchemaName = `${tableName}SelectSchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}/{id}/get-item`,
            operationId: `get${tableName}`,
            summary: `Get ${singularModelName}`,
            description: `Endpoint to retrieve a single ${singularModelName} by ID`,
            tags: [singularModelName],
            parameters: [
                ...OpenAPIUtil.getDefaultApiHeaders(),
                {
                    name: "id",
                    in: "path",
                    required: true,
                    schema: {
                        type: "string",
                        format: "uuid",
                    },
                    description: `ID of the ${singularModelName} to retrieve`,
                },
            ],
            requestBody: {
                required: false,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                select: { $ref: `#/components/schemas/${selectSchemaName}` },
                            },
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Successful response",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        $ref: `#/components/schemas/${tableName}`,
                                    },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static getDefaultApiHeaders() {
        return [];
    }
    static generateUpdateApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating update API if model has no update permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.updateRecordPermissions)) {
            return;
        }
        // Use schema names that are already registered
        const updateSchemaName = `${tableName}UpdateSchema`;
        const readSchemaName = `${tableName}ReadSchema`;
        data.registry.registerPath({
            method: "put",
            path: `${model.crudApiPath}/{id}`,
            operationId: `update${tableName}`,
            summary: `Update ${singularModelName}`,
            description: `Endpoint to update an existing ${singularModelName}`,
            tags: [singularModelName],
            parameters: [
                ...OpenAPIUtil.getDefaultApiHeaders(),
                {
                    name: "id",
                    in: "path",
                    required: true,
                    schema: {
                        type: "string",
                        format: "uuid",
                    },
                    description: `ID of the ${singularModelName} to update`,
                },
            ],
            requestBody: {
                required: true,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                data: {
                                    $ref: `#/components/schemas/${updateSchemaName}`,
                                },
                            },
                            required: ["data"],
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Updated successfully",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        $ref: `#/components/schemas/${readSchemaName}`,
                                    },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateDeleteApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating delete API if model has no delete permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.deleteRecordPermissions)) {
            return;
        }
        data.registry.registerPath({
            method: "delete",
            path: `${model.crudApiPath}/{id}`,
            operationId: `delete${tableName}`,
            summary: `Delete ${singularModelName}`,
            description: `Endpoint to delete a ${singularModelName}`,
            tags: [singularModelName],
            parameters: [
                ...OpenAPIUtil.getDefaultApiHeaders(),
                {
                    name: "id",
                    in: "path",
                    required: true,
                    schema: {
                        type: "string",
                        format: "uuid",
                    },
                    description: `ID of the ${singularModelName} to delete`,
                },
            ],
            responses: Object.assign({ "200": {
                    description: "Deleted successfully",
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static registerModelSchemas(registry, model) {
        const tableName = model.tableName || "UnknownModel";
        const modelType = model.constructor;
        // Register the main model schema (for backwards compatibility)
        const modelSchema = ModelSchema.getModelSchema({
            modelType: modelType,
        });
        registry.register(tableName, modelSchema);
        // Register operation-specific schemas based on permissions
        this.registerOperationSpecificSchemas(registry, tableName, modelType, model);
        // Register query, select, and sort schemas
        this.registerQuerySchemas(registry, tableName, modelType);
    }
    static registerOperationSpecificSchemas(registry, tableName, modelType, model) {
        const canCreate = !this.shouldExcludeApiForPermissions(model.createRecordPermissions);
        const canRead = !this.shouldExcludeApiForPermissions(model.readRecordPermissions);
        const canUpdate = !this.shouldExcludeApiForPermissions(model.updateRecordPermissions);
        const canDelete = !this.shouldExcludeApiForPermissions(model.deleteRecordPermissions);
        if (canCreate) {
            const createSchema = ModelSchema.getCreateModelSchema({
                modelType,
            });
            registry.register(`${tableName}CreateSchema`, createSchema);
        }
        // Register read schema whenever any operation might return it (create/update/read)
        if (canRead || canCreate || canUpdate) {
            const readSchema = ModelSchema.getReadModelSchema({
                modelType,
            });
            registry.register(`${tableName}ReadSchema`, readSchema);
        }
        if (canUpdate) {
            const updateSchema = ModelSchema.getUpdateModelSchema({
                modelType,
            });
            registry.register(`${tableName}UpdateSchema`, updateSchema);
        }
        if (canDelete) {
            const deleteSchema = ModelSchema.getDeleteModelSchema({
                modelType,
            });
            registry.register(`${tableName}DeleteSchema`, deleteSchema);
        }
    }
    static registerQuerySchemas(registry, tableName, modelType) {
        const querySchemaName = `${tableName}QuerySchema`;
        const selectSchemaName = `${tableName}SelectSchema`;
        const sortSchemaName = `${tableName}SortSchema`;
        const groupBySchemaName = `${tableName}GroupBySchema`;
        const querySchema = ModelSchema.getQueryModelSchema({
            modelType: modelType,
        });
        const selectSchema = ModelSchema.getSelectModelSchema({
            modelType: modelType,
        });
        const sortSchema = ModelSchema.getSortModelSchema({
            modelType: modelType,
        });
        const groupBySchema = ModelSchema.getGroupByModelSchema({
            modelType: modelType,
        });
        registry.register(querySchemaName, querySchema);
        registry.register(selectSchemaName, selectSchema);
        registry.register(sortSchemaName, sortSchema);
        registry.register(groupBySchemaName, groupBySchema);
    }
    // Analytics-specific methods
    static registerAnalyticsModelSchemas(registry, model) {
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const modelType = model.constructor;
        // Register the main analytics model schema
        const modelSchema = AnalyticsModelSchema.getModelSchema({
            modelType: modelType,
        });
        registry.register(tableName, modelSchema);
        // Register operation-specific schemas based on permissions
        this.registerAnalyticsOperationSpecificSchemas(registry, tableName, modelType, model);
        // Register query, select, and sort schemas
        this.registerAnalyticsQuerySchemas(registry, tableName, modelType);
    }
    static registerAnalyticsOperationSpecificSchemas(registry, tableName, modelType, model) {
        const canCreate = !this.shouldExcludeApiForPermissions(model.getCreatePermissions());
        const canRead = !this.shouldExcludeApiForPermissions(model.getReadPermissions());
        const canUpdate = !this.shouldExcludeApiForPermissions(model.getUpdatePermissions());
        const canDelete = !this.shouldExcludeApiForPermissions(model.getDeletePermissions());
        if (canCreate) {
            const createSchema = AnalyticsModelSchema.getCreateModelSchema({
                modelType,
            });
            registry.register(`${tableName}CreateSchema`, createSchema);
        }
        if (canRead || canCreate || canUpdate) {
            const readSchema = AnalyticsModelSchema.getModelSchema({
                modelType,
            });
            registry.register(`${tableName}ReadSchema`, readSchema);
        }
        if (canUpdate) {
            const updateSchema = AnalyticsModelSchema.getCreateModelSchema({
                modelType,
            });
            registry.register(`${tableName}UpdateSchema`, updateSchema);
        }
        if (canDelete) {
            const deleteSchema = AnalyticsModelSchema.getModelSchema({
                modelType,
            });
            registry.register(`${tableName}DeleteSchema`, deleteSchema);
        }
    }
    static registerAnalyticsQuerySchemas(registry, tableName, modelType) {
        const querySchemaName = `${tableName}QuerySchema`;
        const selectSchemaName = `${tableName}SelectSchema`;
        const sortSchemaName = `${tableName}SortSchema`;
        const groupBySchemaName = `${tableName}GroupBySchema`;
        const querySchema = AnalyticsModelSchema.getQueryModelSchema({
            modelType: modelType,
        });
        const selectSchema = AnalyticsModelSchema.getSelectModelSchema({
            modelType: modelType,
        });
        const sortSchema = AnalyticsModelSchema.getSortModelSchema({
            modelType: modelType,
        });
        const groupBySchema = AnalyticsModelSchema.getGroupByModelSchema({
            modelType: modelType,
        });
        registry.register(querySchemaName, querySchema);
        registry.register(selectSchemaName, selectSchema);
        registry.register(sortSchemaName, sortSchema);
        registry.register(groupBySchemaName, groupBySchema);
    }
    // Analytics API generation methods
    static generateAnalyticsListApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const singularModelName = model.singularName || tableName;
        // Use schema names that are already registered
        const querySchemaName = `${tableName}QuerySchema`;
        const selectSchemaName = `${tableName}SelectSchema`;
        const sortSchemaName = `${tableName}SortSchema`;
        const groupBySchemaName = `${tableName}GroupBySchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}/get-list`,
            operationId: `list${tableName}`,
            summary: `List ${singularModelName}`,
            description: `Endpoint to list all ${singularModelName} items`,
            tags: [singularModelName],
            parameters: [...OpenAPIUtil.getDefaultApiHeaders()],
            requestBody: {
                required: false,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                query: { $ref: `#/components/schemas/${querySchemaName}` },
                                select: { $ref: `#/components/schemas/${selectSchemaName}` },
                                sort: { $ref: `#/components/schemas/${sortSchemaName}` },
                                groupBy: { $ref: `#/components/schemas/${groupBySchemaName}` },
                                limit: {
                                    type: "number",
                                    description: "Maximum number of items to return. Defaults to 10.",
                                    default: 10,
                                    minimum: 1,
                                },
                                skip: {
                                    type: "number",
                                    description: "Number of items to skip for pagination. Defaults to 0.",
                                    default: 0,
                                    minimum: 0,
                                },
                            },
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Successful response",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        type: "array",
                                        items: {
                                            $ref: `#/components/schemas/${tableName}`,
                                        },
                                    },
                                    count: { type: "number" },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateAnalyticsCountApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const singularModelName = model.singularName || tableName;
        // Use schema name that is already registered
        const querySchemaName = `${tableName}QuerySchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}/count`,
            operationId: `count${tableName}`,
            summary: `Count ${singularModelName}`,
            description: `Endpoint to count ${singularModelName} items`,
            tags: [singularModelName],
            parameters: [...OpenAPIUtil.getDefaultApiHeaders()],
            requestBody: {
                required: false,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                query: { $ref: `#/components/schemas/${querySchemaName}` },
                            },
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Successful response",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    count: { type: "number" },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateAnalyticsCreateApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating create API if model has no create permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.getCreatePermissions())) {
            return;
        }
        // Use schema names that are already registered
        const createSchemaName = `${tableName}CreateSchema`;
        const readSchemaName = `${tableName}ReadSchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}`,
            operationId: `create${tableName}`,
            summary: `Create ${singularModelName}`,
            description: `Endpoint to create a new ${singularModelName}`,
            tags: [singularModelName],
            requestBody: {
                required: true,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                data: {
                                    $ref: `#/components/schemas/${createSchemaName}`,
                                },
                            },
                            required: ["data"],
                        },
                    },
                },
            },
            responses: Object.assign({ "201": {
                    description: "Created successfully",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        $ref: `#/components/schemas/${readSchemaName}`,
                                    },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateAnalyticsGetApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating get API if model has no read permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.getReadPermissions())) {
            return;
        }
        // Use schema name that is already registered
        const selectSchemaName = `${tableName}SelectSchema`;
        data.registry.registerPath({
            method: "post",
            path: `${model.crudApiPath}/{id}`,
            operationId: `get${tableName}`,
            summary: `Get ${singularModelName}`,
            description: `Endpoint to retrieve a single ${singularModelName} by ID`,
            tags: [singularModelName],
            parameters: [
                ...OpenAPIUtil.getDefaultApiHeaders(),
                {
                    name: "id",
                    in: "path",
                    required: true,
                    schema: {
                        type: "string",
                        format: "uuid",
                    },
                    description: `ID of the ${singularModelName} to retrieve`,
                },
            ],
            requestBody: {
                required: false,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                select: { $ref: `#/components/schemas/${selectSchemaName}` },
                            },
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Successful response",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        $ref: `#/components/schemas/${tableName}`,
                                    },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateAnalyticsUpdateApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating update API if model has no update permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.getUpdatePermissions())) {
            return;
        }
        // Use schema names that are already registered
        const updateSchemaName = `${tableName}UpdateSchema`;
        const readSchemaName = `${tableName}ReadSchema`;
        data.registry.registerPath({
            method: "put",
            path: `${model.crudApiPath}/{id}`,
            operationId: `update${tableName}`,
            summary: `Update ${singularModelName}`,
            description: `Endpoint to update an existing ${singularModelName}`,
            tags: [singularModelName],
            parameters: [
                ...OpenAPIUtil.getDefaultApiHeaders(),
                {
                    name: "id",
                    in: "path",
                    required: true,
                    schema: {
                        type: "string",
                        format: "uuid",
                    },
                    description: `ID of the ${singularModelName} to update`,
                },
            ],
            requestBody: {
                required: true,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                data: {
                                    $ref: `#/components/schemas/${updateSchemaName}`,
                                },
                            },
                            required: ["data"],
                        },
                    },
                },
            },
            responses: Object.assign({ "200": {
                    description: "Updated successfully",
                    content: {
                        "application/json": {
                            schema: {
                                type: "object",
                                properties: {
                                    data: {
                                        $ref: `#/components/schemas/${readSchemaName}`,
                                    },
                                },
                            },
                        },
                    },
                } }, this.getGenericStatusResponseSchema()),
        });
    }
    static generateAnalyticsDeleteApiSpec(data) {
        const modelType = data.modelType;
        const model = new modelType();
        const tableName = model.tableName || "UnknownAnalyticsModel";
        const singularModelName = model.singularName || tableName;
        // Skip generating delete API if model has no delete permissions or contains Public/CurrentUser permissions
        if (this.shouldExcludeApiForPermissions(model.getDeletePermissions())) {
            return;
        }
        data.registry.registerPath({
            method: "delete",
            path: `${model.crudApiPath}/{id}`,
            operationId: `delete${tableName}`,
            summary: `Delete ${singularModelName}`,
            description: `Endpoint to delete a ${singularModelName}`,
            tags: [singularModelName],
            parameters: [
                ...OpenAPIUtil.getDefaultApiHeaders(),
                {
                    name: "id",
                    in: "path",
                    required: true,
                    schema: {
                        type: "string",
                        format: "uuid",
                    },
                    description: `ID of the ${singularModelName} to delete`,
                },
            ],
            responses: Object.assign({ "200": {
                    description: "Deleted successfully",
                } }, this.getGenericStatusResponseSchema()),
        });
    }
}
//# sourceMappingURL=OpenAPI.js.map