'use strict';

const node_fs = require('node:fs');
const kit_bb49e233 = require('./cli.de27c2e0.cjs');
require('events');
require('fs');
require('path');
require('util');
require('stream');
require('os');
require('node:module');
require('node:url');
require('node:fs/promises');
require('node:os');
require('crypto');
require('module');
require('perf_hooks');
require('vm');
require('url');
require('assert');
require('buffer');
require('tty');
require('node:path');
require('constants');
require('net');
require('child_process');

const writeTypes = async (remix) => {
  const modulePaths = kit_bb49e233.getModulePaths(remix.options.modulesDir);
  const tsConfig = kit_bb49e233.defu(remix.options.typescript?.tsConfig, {
    compilerOptions: {
      jsx: "preserve",
      target: "ESNext",
      module: "ESNext",
      moduleResolution: "Node",
      skipLibCheck: true,
      strict: remix.options.typescript?.strict ?? false,
      allowJs: true,
      noEmit: true,
      resolveJsonModule: true,
      allowSyntheticDefaultImports: true,
      types: ["node"],
      baseUrl: kit_bb49e233.relative(remix.options.buildDir, remix.options.rootDir),
      paths: {}
    },
    include: [
      "./remix.d.ts",
      kit_bb49e233.join(kit_bb49e233.relative(remix.options.buildDir, remix.options.rootDir), "**/*"),
      ...remix.options.srcDir !== remix.options.rootDir ? [kit_bb49e233.join(kit_bb49e233.relative(remix.options.buildDir, remix.options.srcDir), "**/*")] : [],
      ...remix.options.typescript.includeWorkspace && remix.options.workspaceDir !== remix.options.rootDir ? [kit_bb49e233.join(kit_bb49e233.relative(remix.options.buildDir, remix.options.workspaceDir), "**/*")] : []
    ],
    exclude: []
  });
  const aliases = {
    ...remix.options.alias,
    "#build": remix.options.buildDir
  };
  for (const alias in aliases) {
    const relativePath = kit_bb49e233.isAbsolute(aliases[alias]) ? kit_bb49e233.relative(remix.options.rootDir, aliases[alias]) || "." : aliases[alias];
    const stats = await node_fs.promises.stat(kit_bb49e233.resolve(remix.options.rootDir, relativePath)).catch(() => null);
    tsConfig.compilerOptions = tsConfig.compilerOptions || {};
    if (stats?.isDirectory()) {
      tsConfig.compilerOptions.paths[alias] = [relativePath];
      tsConfig.compilerOptions.paths[`${alias}/*`] = [`${relativePath}/*`];
    } else {
      tsConfig.compilerOptions.paths[alias] = [relativePath.replace(/(?<=\w)\.\w+$/g, "")];
    }
  }
  const references = [
    ...remix.options.modules,
    ...remix.options._modules
  ].filter((f) => typeof f === "string").map((id) => ({ types: kit_bb49e233.getNearestPackage(id, modulePaths)?.name || id }));
  const declarations = [];
  await remix.callHook("prepare:types", { references, declarations, tsConfig });
  const declaration = [
    ...references.map((ref) => {
      if ("path" in ref && kit_bb49e233.isAbsolute(ref.path)) {
        ref.path = kit_bb49e233.relative(remix.options.buildDir, ref.path);
      }
      return `/// <reference ${renderAttrs(ref)} />`;
    }),
    ...declarations,
    "",
    "export {}",
    ""
  ].join("\n");
  async function writeFile() {
    const GeneratedBy = "// Generated by Remix";
    const tsConfigPath = kit_bb49e233.resolve(remix.options.buildDir, "tsconfig.json");
    await node_fs.promises.mkdir(remix.options.buildDir, { recursive: true });
    await node_fs.promises.writeFile(tsConfigPath, GeneratedBy + "\n" + JSON.stringify(tsConfig, null, 2));
    const declarationPath = kit_bb49e233.resolve(remix.options.buildDir, "remix.d.ts");
    await node_fs.promises.writeFile(declarationPath, GeneratedBy + "\n" + declaration);
  }
  await writeFile();
};
function renderAttrs(obj) {
  return Object.entries(obj).map((e) => renderAttr(e[0], e[1])).join(" ");
}
function renderAttr(key, value) {
  return value ? `${key}="${value}"` : "";
}

exports.writeTypes = writeTypes;
