import path from "path";
import prettier from "prettier";
import parserTypescript from "prettier/parser-typescript";
import { swaggerVersion } from "./utils";
import { transformAll } from "./transform/index";
import { GlobalContext, OpenAPI2, OpenAPI3, SchemaObject, SwaggerToTSOptions } from "./types";
export * from "./types"; // expose all types to consumers

export const WARNING_MESSAGE = `/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/


`;

export default function openapiTS(
  schema: OpenAPI2 | OpenAPI3 | Record<string, SchemaObject>,
  options: SwaggerToTSOptions = {}
): string {
  // 1. set up context
  const ctx: GlobalContext = {
    additionalProperties: options.additionalProperties || false,
    auth: options.auth,
    defaultNonNullable: options.defaultNonNullable || false,
    formatter: typeof options.formatter === "function" ? options.formatter : undefined,
    immutableTypes: options.immutableTypes || false,
    rawSchema: options.rawSchema || false,
    version: options.version || swaggerVersion(schema as OpenAPI2 | OpenAPI3),
  } as any;

  // 2. generate output
  let output = WARNING_MESSAGE;
  const rootTypes = transformAll(schema, { ...ctx });
  for (const k of Object.keys(rootTypes)) {
    if (typeof rootTypes[k] !== "string") continue;
    output += `export interface ${k} {\n  ${rootTypes[k]}\n}\n\n`;
  }

  // 3. Prettify
  let prettierOptions: prettier.Options = {
    parser: "typescript",
    plugins: [parserTypescript],
  };
  if (options && options.prettierConfig) {
    try {
      const userOptions = prettier.resolveConfig.sync(path.resolve(process.cwd(), options.prettierConfig));
      prettierOptions = {
        ...(userOptions || {}),
        ...prettierOptions,
        plugins: [...(prettierOptions.plugins as prettier.Plugin[]), ...((userOptions && userOptions.plugins) || [])],
      };
    } catch (err) {
      console.error(`❌ ${err}`);
    }
  }
  return prettier.format(output, prettierOptions);
}
