import endpoints from "../endpoints.js";
import config from "../../../config/index.js";
import { errors as basicErrors } from "./errors.js";
import { schemas, convertSchemaToOpenApiSchema } from "./schemas.js";
export function genOpenapiSpec() {
    const spec = {
        openapi: "3.0.0",
        info: {
            version: "v1",
            title: "Iceshrimp API",
            "x-logo": {
                url: "/static-assets/api-doc.png"
            }
        },
        externalDocs: {
            description: "Repository",
            url: "https://iceshrimp.dev/iceshrimp/iceshrimp"
        },
        servers: [
            {
                url: config.apiUrl
            }
        ],
        paths: {},
        components: {
            schemas: schemas,
            securitySchemes: {
                ApiKeyAuth: {
                    type: "apiKey",
                    in: "body",
                    name: "i"
                },
                // TODO: change this to oauth2 when the remaining oauth stuff is set up
                Bearer: {
                    type: "http",
                    scheme: "bearer"
                }
            }
        }
    };
    for (const endpoint of endpoints.filter((ep)=>!ep.meta.secure)){
        const errors = {};
        if (endpoint.meta.errors) {
            for (const e of Object.values(endpoint.meta.errors)){
                errors[e.code] = {
                    value: {
                        error: e
                    }
                };
            }
        }
        const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {};
        let desc = (endpoint.meta.description ? endpoint.meta.description : "No description provided.") + "\n\n";
        desc += `**Credential required**: *${endpoint.meta.requireCredential ? "Yes" : "No"}*`;
        if (endpoint.meta.kind) {
            const kind = endpoint.meta.kind;
            desc += ` / **Permission**: *${kind}*`;
        }
        const requestType = endpoint.meta.requireFile ? "multipart/form-data" : "application/json";
        const schema = endpoint.params;
        if (endpoint.meta.requireFile) {
            schema.properties.file = {
                type: "string",
                format: "binary",
                description: "The file contents."
            };
            schema.required.push("file");
        }
        const security = [
            {
                ApiKeyAuth: []
            },
            {
                Bearer: []
            }
        ];
        if (!endpoint.meta.requireCredential) {
            // add this to make authentication optional
            security.push({});
        }
        const info = {
            operationId: endpoint.name,
            summary: endpoint.name,
            description: desc,
            externalDocs: {
                description: "Source code",
                url: `https://iceshrimp.dev/iceshrimp/iceshrimp/src/branch/dev/packages/backend/src/server/api/endpoints/${endpoint.name}.ts`
            },
            tags: endpoint.meta.tags || undefined,
            security,
            requestBody: {
                required: true,
                content: {
                    [requestType]: {
                        schema
                    }
                }
            },
            responses: {
                ...endpoint.meta.res ? {
                    "200": {
                        description: "OK (with results)",
                        content: {
                            "application/json": {
                                schema: resSchema
                            }
                        }
                    }
                } : {
                    "204": {
                        description: "OK (without any results)"
                    }
                },
                "400": {
                    description: "Client error",
                    content: {
                        "application/json": {
                            schema: {
                                $ref: "#/components/schemas/Error"
                            },
                            examples: {
                                ...errors,
                                ...basicErrors["400"]
                            }
                        }
                    }
                },
                "401": {
                    description: "Authentication error",
                    content: {
                        "application/json": {
                            schema: {
                                $ref: "#/components/schemas/Error"
                            },
                            examples: basicErrors["401"]
                        }
                    }
                },
                "403": {
                    description: "Forbidden error",
                    content: {
                        "application/json": {
                            schema: {
                                $ref: "#/components/schemas/Error"
                            },
                            examples: basicErrors["403"]
                        }
                    }
                },
                "418": {
                    description: "I'm Calc",
                    content: {
                        "application/json": {
                            schema: {
                                $ref: "#/components/schemas/Error"
                            },
                            examples: basicErrors["418"]
                        }
                    }
                },
                ...endpoint.meta.limit ? {
                    "429": {
                        description: "Too many requests",
                        content: {
                            "application/json": {
                                schema: {
                                    $ref: "#/components/schemas/Error"
                                },
                                examples: basicErrors["429"]
                            }
                        }
                    }
                } : {},
                "500": {
                    description: "Internal server error",
                    content: {
                        "application/json": {
                            schema: {
                                $ref: "#/components/schemas/Error"
                            },
                            examples: basicErrors["500"]
                        }
                    }
                }
            }
        };
        const path = {
            post: info
        };
        if (endpoint.meta.allowGet) {
            path.get = {
                ...info
            };
            // API Key authentication is not permitted for GET requests
            path.get.security = path.get.security.filter((elem)=>!Object.prototype.hasOwnProperty.call(elem, "ApiKeyAuth"));
        }
        spec.paths[`/${endpoint.name}`] = path;
    }
    return spec;
}
