"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeSchemas = exports.isCompatible = void 0;
const schema_types_1 = require("./schema.types");
const isCompatible = (schema, otherSchema) => {
    if (schema.type !== otherSchema.type) {
        return false; // different types
    }
    if (schema.type === 'array' && otherSchema.type === 'array') {
        return (0, exports.isCompatible)(schema.items, otherSchema.items);
    }
    if (schema.type === 'object' && otherSchema.type === 'object') {
        const keysFromSchema = Object.keys(schema.properties);
        const keysFromOtherSchema = Object.keys(otherSchema.properties);
        const commonKeys = keysFromSchema.filter((key) => keysFromOtherSchema.includes(key));
        if (schema.required?.some((key) => !keysFromOtherSchema.includes(key))) {
            return false; // some required keys are not present in the other schema
        }
        else if (otherSchema.required?.some((key) => !keysFromSchema.includes(key))) {
            return false; // some required keys are not present in the schema
        }
        if (commonKeys.length > 0) {
            return commonKeys.every((key) => (0, exports.isCompatible)(schema.properties[key], otherSchema.properties[key]));
        }
    }
    return true;
};
exports.isCompatible = isCompatible;
const mergeSchemas = (schema, otherSchema) => {
    if (!(0, exports.isCompatible)(schema, otherSchema)) {
        throw new schema_types_1.JsonSchemaError('Cannot merge schemas of different types');
    }
    if (schema.type === 'object' && otherSchema.type === 'object') {
        const mergedProperties = { ...schema.properties, ...otherSchema.properties };
        const otherSchemaKeys = Object.keys(otherSchema.properties).reduce((acc, key) => ({ ...acc, [key]: true }), {});
        for (const key in schema.properties) {
            if (otherSchemaKeys[key]) {
                mergedProperties[key] = (0, exports.mergeSchemas)(schema.properties[key], otherSchema.properties[key]);
            }
        }
        const mergedRequired = new Set([...(schema.required ?? []), ...(otherSchema.required ?? [])]);
        return {
            type: 'object',
            properties: mergedProperties,
            required: Array.from(mergedRequired),
        };
    }
    if (schema.type === 'array' && otherSchema.type === 'array') {
        return {
            type: 'array',
            items: (0, exports.mergeSchemas)(schema.items, otherSchema.items),
        };
    }
    return {
        type: schema.type,
        description: schema.description ?? otherSchema.description,
    };
};
exports.mergeSchemas = mergeSchemas;
