import { performance } from 'node:perf_hooks';
import * as changeCase from 'change-case';
import ts from 'typescript';
import { tsModifiers, tsPropertyIndex, QUESTION_TOKEN, addJSDocComment, NEVER } from '../lib/ts.mjs';
import { getEntries, createRef, debug } from '../lib/utils.mjs';
import transformHeaderObject from './header-object.mjs';
import transformParameterObject from './parameter-object.mjs';
import transformPathItemObject from './path-item-object.mjs';
import transformRequestBodyObject from './request-body-object.mjs';
import transformResponseObject from './response-object.mjs';
import transformSchemaObject from './schema-object.mjs';

function isEnumSchema(schema) {
  return typeof schema === "object" && schema !== null && !Array.isArray(schema) && "enum" in schema && Array.isArray(schema.enum) && (!("type" in schema) || schema.type !== "object") && !("properties" in schema) && !("additionalProperties" in schema);
}
const transformers = {
  schemas: transformSchemaObject,
  responses: transformResponseObject,
  parameters: transformParameterObject,
  requestBodies: transformRequestBodyObject,
  headers: transformHeaderObject,
  pathItems: transformPathItemObject
};
function transformComponentsObject(componentsObject, ctx) {
  const type = [];
  const rootTypeAliases = {};
  for (const key of Object.keys(transformers)) {
    const componentT = performance.now();
    const items = [];
    if (componentsObject[key]) {
      for (const [name, item] of getEntries(componentsObject[key], ctx)) {
        let subType = transformers[key](item, {
          path: createRef(["components", key, name]),
          schema: item,
          ctx
        });
        let hasQuestionToken = false;
        if (ctx.transform) {
          const result = ctx.transform(item, {
            path: createRef(["components", key, name]),
            schema: item,
            ctx
          });
          if (result) {
            if ("schema" in result) {
              subType = result.schema;
              hasQuestionToken = result.questionToken;
            } else {
              subType = result;
            }
          }
        }
        const property = ts.factory.createPropertySignature(
          /* modifiers     */
          tsModifiers({ readonly: ctx.immutable }),
          /* name          */
          tsPropertyIndex(name),
          /* questionToken */
          hasQuestionToken ? QUESTION_TOKEN : void 0,
          /* type          */
          subType
        );
        addJSDocComment(item, property);
        items.push(property);
        if (ctx.rootTypes) {
          const shouldSkipEnumSchema = ctx.enum && key === "schemas" && isEnumSchema(item);
          if (!shouldSkipEnumSchema) {
            const componentKey = changeCase.pascalCase(singularizeComponentKey(key));
            const componentName = ctx.rootTypesKeepCasing && key === "schemas" ? name : changeCase.pascalCase(name);
            let aliasName = `${componentKey}${componentName}`;
            let conflictCounter = 1;
            while (rootTypeAliases[aliasName] !== void 0) {
              conflictCounter++;
              aliasName = `${componentKey}${componentName}_${conflictCounter}`;
            }
            const ref = ts.factory.createTypeReferenceNode(`components['${key}']['${name}']`);
            if (ctx.rootTypesNoSchemaPrefix && key === "schemas") {
              aliasName = aliasName.replace(componentKey, "");
            }
            const typeAlias = ts.factory.createTypeAliasDeclaration(
              /* modifiers      */
              tsModifiers({ export: true }),
              /* name           */
              aliasName,
              /* typeParameters */
              void 0,
              /* type           */
              ref
            );
            rootTypeAliases[aliasName] = typeAlias;
          }
        }
      }
    }
    type.push(
      ts.factory.createPropertySignature(
        /* modifiers     */
        void 0,
        /* name          */
        tsPropertyIndex(key),
        /* questionToken */
        void 0,
        /* type          */
        items.length ? ts.factory.createTypeLiteralNode(items) : NEVER
      )
    );
    debug(`Transformed components \u2192 ${key}`, "ts", performance.now() - componentT);
  }
  let rootTypes = [];
  if (ctx.rootTypes) {
    rootTypes = Object.keys(rootTypeAliases).map((k) => rootTypeAliases[k]);
  }
  return [ts.factory.createTypeLiteralNode(type), ...rootTypes];
}
function singularizeComponentKey(key) {
  switch (key) {
    // Handle special singular case
    case "requestBodies":
      return "requestBody";
    // Default to removing the "s"
    default:
      return key.slice(0, -1);
  }
}

export { transformComponentsObject as default, isEnumSchema, singularizeComponentKey };
//# sourceMappingURL=components-object.mjs.map
