import { expect } from "chai";
import { buildUnifiedUniverse } from "./unified-universe.js";
const emptyAssemblyCatalog = () => ({
    entries: new Map(),
    tsNameToTypeId: new Map(),
    clrNameToTypeId: new Map(),
    namespaceToTypeIds: new Map(),
});
const makeAssemblyTypeId = (stableId, clrName, assemblyName, tsName) => ({
    stableId,
    clrName,
    assemblyName,
    tsName,
});
const makeRegistry = (entry) => ({
    resolveNominal: (fqName) => fqName === entry.fullyQualifiedName ? entry : undefined,
    resolveBySimpleName: (simpleName) => simpleName === entry.name ? entry : undefined,
    getFQName: (simpleName) => simpleName === entry.name ? entry.fullyQualifiedName : undefined,
    getFQNames: (simpleName) => simpleName === entry.name ? [entry.fullyQualifiedName] : [],
    getMemberType: (fqNominal, memberName) => {
        if (fqNominal !== entry.fullyQualifiedName)
            return undefined;
        return entry.members.get(memberName)?.type;
    },
    getHeritageTypes: (fqNominal) => fqNominal === entry.fullyQualifiedName ? entry.heritage : [],
    getAllTypeNames: () => [entry.fullyQualifiedName],
    hasType: (fqName) => fqName === entry.fullyQualifiedName,
});
const optionalMember = (type, isOptional) => ({
    kind: "property",
    name: "count",
    type,
    isOptional,
    isReadonly: false,
});
describe("buildUnifiedUniverse", () => {
    it("lifts optional source property types to include undefined", () => {
        const entry = {
            kind: "interface",
            name: "Foo",
            fullyQualifiedName: "MyApp.Foo",
            ownerIdentity: "project",
            isDeclarationFile: false,
            typeParameters: [],
            members: new Map([
                [
                    "count",
                    optionalMember({ kind: "primitiveType", name: "int" }, true),
                ],
            ]),
            heritage: [],
        };
        const catalog = buildUnifiedUniverse(makeRegistry(entry), emptyAssemblyCatalog(), "project");
        const fooId = catalog.resolveTsName("Foo");
        expect(fooId).to.not.equal(undefined);
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const member = catalog.getMember(fooId, "count");
        expect(member?.type?.kind).to.equal("unionType");
        if (member?.type?.kind === "unionType") {
            const hasUndefined = member.type.types.some((t) => t.kind === "primitiveType" && t.name === "undefined");
            const hasInt = member.type.types.some((t) => t.kind === "primitiveType" && t.name === "int");
            expect(hasUndefined).to.equal(true);
            expect(hasInt).to.equal(true);
        }
    });
    it("does not duplicate explicit undefined in optional source types", () => {
        const entry = {
            kind: "interface",
            name: "Foo",
            fullyQualifiedName: "MyApp.Foo",
            ownerIdentity: "project",
            isDeclarationFile: false,
            typeParameters: [],
            members: new Map([
                [
                    "count",
                    optionalMember({
                        kind: "unionType",
                        types: [
                            { kind: "primitiveType", name: "int" },
                            { kind: "primitiveType", name: "undefined" },
                        ],
                    }, true),
                ],
            ]),
            heritage: [],
        };
        const catalog = buildUnifiedUniverse(makeRegistry(entry), emptyAssemblyCatalog(), "project");
        const fooId = catalog.resolveTsName("Foo");
        expect(fooId).to.not.equal(undefined);
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const member = catalog.getMember(fooId, "count");
        expect(member?.type?.kind).to.equal("unionType");
        if (member?.type?.kind === "unionType") {
            const undefinedCount = member.type.types.filter((t) => t.kind === "primitiveType" && t.name === "undefined").length;
            expect(undefinedCount).to.equal(1);
        }
    });
    it("keeps assembly identity for entries explicitly marked to preserve it", () => {
        const entry = {
            kind: "class",
            name: "Error",
            fullyQualifiedName: "Error",
            ownerIdentity: "project",
            isDeclarationFile: true,
            preservesAssemblyIdentity: true,
            typeParameters: [],
            members: new Map(),
            heritage: [],
        };
        const errorTypeId = makeAssemblyTypeId("js:js.Error", "js.Error", "js", "Error");
        const assemblyEntry = {
            typeId: errorTypeId,
            kind: "class",
            typeParameters: [],
            heritage: [],
            members: new Map(),
            origin: "assembly",
            accessibility: "public",
            isAbstract: false,
            isSealed: false,
            isStatic: false,
        };
        const catalog = buildUnifiedUniverse(makeRegistry(entry), {
            entries: new Map([[errorTypeId.stableId, assemblyEntry]]),
            tsNameToTypeId: new Map([[errorTypeId.tsName, errorTypeId]]),
            clrNameToTypeId: new Map([[errorTypeId.clrName, errorTypeId]]),
            namespaceToTypeIds: new Map(),
        }, "project");
        expect(catalog.resolveTsName("Error")).to.deep.equal(errorTypeId);
    });
});
//# sourceMappingURL=unified-universe.test.js.map