/**
 * Anonymous Type Naming & Member Conversion
 *
 * Named type generation, object-to-class member conversion, and behavioral
 * object type name creation for anonymous type lowering.
 */
import { collectTypeParameterNames, computeShapeSignature, generateShapeHash, generateModuleHash, addUndefinedToType, normalizeStructuralPropertySignature, stripUndefinedFromType, } from "./anon-type-shape-analysis.js";
/**
 * Convert interface members to class property declarations
 */
export const interfaceMembersToClassMembers = (members) => {
    return members
        .filter((m) => m.kind === "propertySignature")
        .map((m) => {
        const normalizedMember = normalizeStructuralPropertySignature(m);
        const isOptional = normalizedMember.isOptional;
        return {
            kind: "propertyDeclaration",
            name: normalizedMember.name,
            type: isOptional
                ? addUndefinedToType(normalizedMember.type)
                : normalizedMember.type,
            initializer: undefined,
            emitAsAutoProperty: true,
            isStatic: false,
            isReadonly: normalizedMember.isReadonly ?? false,
            accessibility: "public",
            isRequired: !isOptional,
        };
    });
};
export const classMembersToInterfaceMembers = (members) => members.flatMap((member) => {
    if (member.kind === "propertyDeclaration" &&
        member.type &&
        member.accessibility === "public" &&
        !member.isStatic) {
        const strippedType = stripUndefinedFromType(member.type);
        const isOptional = strippedType !== member.type;
        return {
            kind: "propertySignature",
            name: member.name,
            type: isOptional ? strippedType : member.type,
            isOptional,
            isReadonly: member.isReadonly,
        };
    }
    if (member.kind === "methodDeclaration" &&
        member.accessibility === "public" &&
        !member.isStatic) {
        return {
            kind: "methodSignature",
            name: member.name,
            typeParameters: member.typeParameters,
            parameters: member.parameters,
            returnType: member.returnType,
            overloadFamily: member.overloadFamily,
        };
    }
    return [];
});
/**
 * Get or create a generated type name for an object type shape
 */
export const getOrCreateTypeName = (objectType, ctx) => {
    const signature = computeShapeSignature(objectType);
    const existing = ctx.shapeToName.get(signature);
    if (existing) {
        return existing;
    }
    // Generate name with module hash prefix to avoid collisions across modules
    const moduleHash = generateModuleHash(ctx.moduleFilePath);
    const shapeHash = generateShapeHash(signature);
    // Keep a stable compiler-synthesized prefix for cross-module type tracking.
    // Dependency/soundness passes treat __Anon_* as compiler-generated types.
    const name = `__Anon_${moduleHash}_${shapeHash}`;
    ctx.shapeToName.set(signature, name);
    const typeParamNames = new Set();
    for (const member of objectType.members) {
        if (member.kind === "propertySignature") {
            collectTypeParameterNames(member.type, typeParamNames);
        }
        else if (member.kind === "methodSignature") {
            for (const p of member.parameters) {
                if (p.type)
                    collectTypeParameterNames(p.type, typeParamNames);
            }
            if (member.returnType)
                collectTypeParameterNames(member.returnType, typeParamNames);
        }
    }
    const orderedTypeParams = Array.from(typeParamNames).sort();
    // Create a class declaration (not interface) so it can be instantiated
    const declaration = {
        kind: "classDeclaration",
        name,
        typeParameters: orderedTypeParams.length > 0
            ? orderedTypeParams.map((tp) => ({
                kind: "typeParameter",
                name: tp,
            }))
            : undefined,
        superClass: undefined,
        implements: [],
        members: interfaceMembersToClassMembers(objectType.members),
        isExported: true, // Public to avoid inconsistent accessibility errors
        isStruct: false,
    };
    ctx.generatedDeclarations.push(declaration);
    return name;
};
export const isReusableStructuralCarrierName = (name) => name.startsWith("__Anon_") || name.startsWith("__Rest_");
export const getOrCreateBehavioralObjectTypeName = (objectType, behaviorMembers, sourceLocation, ctx) => {
    const moduleHash = generateModuleHash(ctx.moduleFilePath);
    const locationKey = sourceLocation
        ? `${sourceLocation.file}:${sourceLocation.line}:${sourceLocation.column}`
        : `${ctx.moduleFilePath}:behavior`;
    const behaviorSignature = [
        "behavior",
        locationKey,
        computeShapeSignature(objectType),
        ...behaviorMembers.map((member) => member.kind === "methodDeclaration"
            ? `method:${member.name}`
            : member.kind === "propertyDeclaration"
                ? `property:${member.name}`
                : `ctor:${member.parameters.length}`),
    ].join("|");
    const existing = ctx.shapeToName.get(behaviorSignature);
    if (existing) {
        return existing;
    }
    const name = `__Anon_${moduleHash}_${generateShapeHash(behaviorSignature)}`;
    ctx.shapeToName.set(behaviorSignature, name);
    const behaviorPropertyNames = new Set(behaviorMembers
        .filter((member) => member.kind === "propertyDeclaration")
        .map((member) => member.name));
    const generatedMembers = [
        ...interfaceMembersToClassMembers(objectType.members).filter((member) => member.kind !== "propertyDeclaration" ||
            !behaviorPropertyNames.has(member.name)),
        ...behaviorMembers,
    ];
    ctx.generatedDeclarations.push({
        kind: "classDeclaration",
        name,
        typeParameters: undefined,
        superClass: undefined,
        implements: [],
        members: generatedMembers,
        isExported: true,
        isStruct: false,
    });
    return name;
};
//# sourceMappingURL=anon-type-naming.js.map