import { useNuxt, defineNuxtModule, createResolver, useLogger, addTypeTemplate, addImportsDir, addServerImportsDir, addPlugin, hasNuxtModule, hasNuxtModuleCompatibility, addTemplate, addServerHandler, addPrerenderRoutes, addServerPlugin } from '@nuxt/kit';
import { initSiteConfig, updateSiteConfig, getSiteConfigStack } from 'nuxt-site-config-kit';
import { relative } from 'pathe';
import { readPackageJSON } from 'pkg-types';
import { validateSiteConfigStack } from 'site-config-stack';
import { parseURL } from 'ufo';
import { existsSync } from 'node:fs';
import { addCustomTab } from '@nuxt/devtools-kit';

const DEVTOOLS_UI_ROUTE = "/__nuxt-site-config";
const DEVTOOLS_UI_LOCAL_PORT = 3030;
function setupDevToolsUI(resolve, nuxt = useNuxt()) {
  const clientPath = resolve("./client");
  const isProductionBuild = existsSync(clientPath);
  if (isProductionBuild) {
    nuxt.hook("vite:serverCreated", async (server) => {
      const sirv = await import('sirv').then((r) => r.default || r);
      server.middlewares.use(
        DEVTOOLS_UI_ROUTE,
        sirv(clientPath, { dev: true, single: true })
      );
    });
  } else {
    nuxt.hook("vite:extendConfig", (config) => {
      config.server = { ...config.server, proxy: { ...config.server?.proxy } };
      config.server.proxy[DEVTOOLS_UI_ROUTE] = {
        target: `http://localhost:${DEVTOOLS_UI_LOCAL_PORT}${DEVTOOLS_UI_ROUTE}`,
        changeOrigin: true,
        followRedirects: true,
        rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
      };
    });
  }
  addCustomTab({
    // unique identifier
    name: "nuxt-site-config",
    // title to display in the tab
    title: "Site Config",
    // any icon from Iconify, or a URL to an image
    icon: "carbon:settings-check",
    // iframe view
    view: {
      type: "iframe",
      src: DEVTOOLS_UI_ROUTE
    }
  });
}

const module$1 = defineNuxtModule({
  meta: {
    name: "nuxt-site-config",
    compatibility: {
      nuxt: ">=3.9.0"
    },
    configKey: "site"
  },
  moduleDependencies: {
    "@nuxtjs/i18n": {
      version: ">=8",
      optional: true
    },
    "nuxt-i18n-micro": {
      version: ">=1",
      optional: true
    }
  },
  defaults(nuxt) {
    return {
      enabled: true,
      debug: nuxt.options.debug || false
    };
  },
  async setup(config, nuxt) {
    const { resolve } = createResolver(import.meta.url);
    const { name, version } = await readPackageJSON(resolve("../package.json"));
    const logger = useLogger(name);
    logger.level = config.debug ? 4 : 3;
    if (config.enabled === false) {
      logger.debug("The module is disabled, skipping setup.");
      return;
    }
    await initSiteConfig();
    const siteConfigInput = { ...config };
    delete siteConfigInput.debug;
    delete siteConfigInput.enabled;
    updateSiteConfig({
      // we should allow environment variables to override the site config
      _priority: -3,
      _context: "nuxt-site-config:config",
      ...siteConfigInput
    });
    nuxt.hook("modules:done", async () => {
      await nuxt.callHook("site-config:resolve");
      const errors = validateSiteConfigStack(getSiteConfigStack(), { dev: nuxt.options.dev });
      if (errors.length > 0) {
        logger.warn("[Nuxt Site Config] Invalid config provided, please correct:");
        for (const error of errors)
          logger.log(`  - ${error}`);
        logger.log("");
      }
      nuxt.options.runtimeConfig["nuxt-site-config"] = {
        stack: getSiteConfigStack().stack,
        version,
        debug: config.debug,
        multiTenancy: (config.multiTenancy || [])?.map((t) => {
          t.hosts = (t.hosts || []).map((h) => parseURL(h, "https://").host?.replace(/:\d+$/, "")).filter(Boolean);
          if (!t.hosts.length) {
            return false;
          }
          return t;
        }).filter(Boolean)
      };
    });
    addTypeTemplate({
      filename: "module/nuxt-site-config.d.ts",
      getContents: (data) => {
        const typesPath = relative(resolve(data.nuxt.options.rootDir, data.nuxt.options.buildDir, "module"), resolve("runtime/types"));
        return `// Generated by nuxt-site-config

declare module 'nitropack' {
  interface NitroRouteRules {
    site?: import('${typesPath}').SiteConfigInput
  }
  interface NitroRouteConfig {
    site?: import('${typesPath}').SiteConfig
  }
  interface NitroRuntimeHooks {
    'site-config:init': (ctx: import('${typesPath}').HookSiteConfigInitContext) => void | Promise<void>
  }
}

declare module 'h3' {
  interface H3EventContext {
    siteConfig: import('${typesPath}').SiteConfigStack
    siteConfigNitroOrigin: string
  }
}


declare module '@nuxt/schema' {
  interface Nuxt {
    _siteConfig?: import('${typesPath}').SiteConfigStack
  }
}
declare module 'nuxt/app' {
  interface NuxtApp {
     $nuxtSiteConfig: import('${typesPath}').SiteConfigStack
  }
}
declare module '#app' {
  interface NuxtApp {
    $nuxtSiteConfig: import('${typesPath}').SiteConfigStack
  }
}


declare global {
  interface Window {
    __NUXT_SITE_CONFIG__: import('${typesPath}').SiteConfigResolved
  }
}

export {}
`;
      }
    }, {
      nitro: true,
      nuxt: true
    });
    addImportsDir(resolve("./runtime/app/composables"));
    if (process.env.playground) {
      nuxt.options.alias["site-config-stack/urls"] = resolve("../../site-config/src/urls");
      nuxt.options.alias["site-config-stack"] = resolve("../../site-config/src/index");
    }
    addServerImportsDir(resolve("./runtime/server/composables"));
    nuxt.options.alias["#site-config"] = resolve("./runtime");
    nuxt.options.nitro.alias = nuxt.options.nitro.alias || {};
    nuxt.options.nitro.alias["#internal/nuxt-site-config"] = resolve("./runtime/server/composable-barrel-deprecated");
    nuxt.options.build.transpile.push("site-config-stack");
    addPlugin({
      src: resolve("./runtime/app/plugins/0.siteConfig")
    });
    if (hasNuxtModule("@nuxtjs/i18n")) {
      const isNuxtI18nV9 = await hasNuxtModuleCompatibility("@nuxtjs/i18n", ">=9");
      addTemplate({
        filename: "nuxt-site-config/i18n-plugin-deps.mjs",
        getContents() {
          const v9 = ["i18n:plugin", "i18n:plugin:ssg-detect", "i18n:plugin:route-locale-detect"];
          const v8 = ["i18n:plugin"];
          return `export const i18nPluginDeps = ${JSON.stringify(isNuxtI18nV9 ? v9 : v8)}`;
        }
      });
      addPlugin({
        src: resolve("./runtime/app/plugins/i18n")
      });
      const baseUrl = nuxt.options.i18n?.baseUrl;
      const locale = nuxt.options.i18n?.locales?.find((l) => l.code === nuxt.options.i18n?.defaultLocale);
      updateSiteConfig({
        _context: "@nuxtjs/i18n",
        url: typeof baseUrl === "string" ? baseUrl : void 0,
        // @ts-expect-error untyped
        defaultLocale: locale?.language || locale?.iso || nuxt.options.i18n?.defaultLocale
      });
    } else if (hasNuxtModule("nuxt-i18n-micro")) {
      addPlugin({
        src: resolve("./runtime/app/plugins/i18n-micro")
      });
      const baseUrl = nuxt.options.i18n?.baseUrl;
      const locale = nuxt.options.i18n?.locales?.find((l) => l.code === nuxt.options.i18n?.defaultLocale);
      updateSiteConfig({
        _context: "nuxt-i18n-micro",
        url: typeof baseUrl === "string" ? baseUrl : void 0,
        // @ts-expect-error untyped
        defaultLocale: locale?.language || locale?.iso || nuxt.options.i18n?.defaultLocale
      });
    }
    addServerHandler({
      middleware: true,
      handler: resolve("./runtime/server/middleware/init")
    });
    if (config.debug || nuxt.options.dev) {
      addServerHandler({
        route: "/__site-config__/debug.json",
        handler: resolve("./runtime/server/routes/__site-config__/debug")
      });
      if (nuxt.options._generate)
        addPrerenderRoutes("/__site-config__/debug.json");
    }
    if (nuxt.options.dev)
      setupDevToolsUI(resolve);
    addServerPlugin(resolve("./runtime/server/plugins/injectState"));
  }
});

export { module$1 as default };
