import { isNonNullish } from "@fern-api/ui-core-utils";
import { BaseOpenApiV3_1ConverterNode, } from "../../../BaseOpenApiV3_1Converter.node";
import { maybeSingleValueToArray } from "../../../utils/maybeSingleValueToArray";
import { singleUndefinedArrayIfNullOrEmpty } from "../../../utils/singleUndefinedArrayIfNullOrEmpty";
import { STATUS_CODE_MESSAGES } from "../../../utils/statusCodes";
import { convertOperationObjectProperties } from "../parameters/ParameterBaseObjectConverter.node";
import { ResponseObjectConverterNode } from "./ResponseObjectConverter.node";
export class ResponsesObjectConverterNode extends BaseOpenApiV3_1ConverterNode {
    path;
    method;
    requests;
    shapes;
    responsesByStatusCode;
    errorsByStatusCode;
    constructor(args, path, method, requests, shapes) {
        super(args);
        this.path = path;
        this.method = method;
        this.requests = requests;
        this.shapes = shapes;
        this.safeParse();
    }
    parse() {
        const defaultResponse = this.input.default;
        Object.entries(this.input).forEach(([statusCode, response]) => {
            if (statusCode === "default") {
                return;
            }
            if (parseInt(statusCode) >= 400) {
                this.errorsByStatusCode ??= {};
                this.errorsByStatusCode[statusCode] = new ResponseObjectConverterNode({
                    input: {
                        ...defaultResponse,
                        ...response,
                    },
                    context: this.context,
                    accessPath: this.accessPath,
                    pathId: "errors",
                }, this.path, this.method, parseInt(statusCode), [], this.shapes);
            }
            else {
                this.responsesByStatusCode ??= {};
                this.responsesByStatusCode[statusCode] =
                    new ResponseObjectConverterNode({
                        input: response,
                        context: this.context,
                        accessPath: this.accessPath,
                        pathId: "responses",
                    }, this.path, this.method, parseInt(statusCode), this.requests, this.shapes);
            }
        });
    }
    convertResponseObjectToHttpResponses() {
        return Object.entries(this.responsesByStatusCode ?? {})
            .flatMap(([statusCode, response]) => {
            const bodies = response.convert();
            if (bodies == null) {
                return undefined;
            }
            return singleUndefinedArrayIfNullOrEmpty(convertOperationObjectProperties(response.headers)).flatMap((headers) => bodies?.map((body) => ({
                headers,
                response: {
                    statusCode: parseInt(statusCode),
                    body,
                    description: response.description,
                },
                examples: (response.responses ?? []).flatMap((res) => (res.examples ?? [])
                    .map((example) => example.convert())
                    .filter(isNonNullish)),
            })));
        })
            .filter(isNonNullish);
    }
    convertResponseObjectToErrors() {
        return Object.entries(this.errorsByStatusCode ?? {})
            .flatMap(([statusCode, response]) => {
            return response.responses?.flatMap((res) => {
                const schema = res.schema;
                const maybeShapes = maybeSingleValueToArray(schema?.convert());
                if (schema == null) {
                    return undefined;
                }
                return maybeShapes
                    ?.map((shape) => ({
                    statusCode: parseInt(statusCode),
                    shape,
                    description: response.description ?? schema.description,
                    availability: schema.availability?.convert(),
                    name: schema.name ??
                        STATUS_CODE_MESSAGES[parseInt(statusCode)] ??
                        "UNKNOWN ERROR",
                    examples: res.examples
                        ?.map((example) => {
                        const convertedExample = example.convert();
                        if (convertedExample == null) {
                            return undefined;
                        }
                        if (convertedExample.responseBody?.type !== "json") {
                            return undefined;
                        }
                        return {
                            name: convertedExample.name,
                            description: convertedExample.description,
                            responseBody: convertedExample.responseBody,
                        };
                    })
                        .filter(isNonNullish),
                }))
                    .filter(isNonNullish);
            });
        })
            .filter(isNonNullish);
    }
    convert() {
        return {
            responses: this.convertResponseObjectToHttpResponses(),
            errors: this.convertResponseObjectToErrors(),
        };
    }
}
