// @ts-check
import { defineConfig } from "astro/config";
import { unified } from "@astrojs/markdown-remark";

import starlight from "@astrojs/starlight";
import sitemap from "@astrojs/sitemap";
import vercel from "@astrojs/vercel";
import node from "@astrojs/node";
import partytown from "@astrojs/partytown";
import tailwindcss from "@tailwindcss/vite";

import starlightLinksValidator from "starlight-links-validator";
import starlightLlmsTxt from "starlight-llms-txt";
import d2 from "astro-d2";

import { sidebar } from "./src/data/sidebar.ts";
import { rehypeChangelogAnchors } from "./src/lib/rehype-changelog-anchors.ts";

// Check if we're in Vercel environment
const isVercel = globalThis.process?.env?.VERCEL;

/**
 * Wraps the `starlight-llms-txt` plugin so it still generates `/llms-full.txt`
 * and `/llms-small.txt`, but does NOT inject its own `/llms.txt` route. That
 * frees `/llms.txt` for our hand-curated index at `public/llms.txt`, which the
 * plugin's generated entrypoint can't reproduce (its body is a fixed template).
 *
 * The plugin (node_modules/starlight-llms-txt/index.ts) injects its routes from
 * inside an Astro integration's `astro:config:setup` hook. We intercept the
 * `addIntegration` call, then wrap that integration's `injectRoute` to drop the
 * single `/llms.txt` pattern and pass every other route through untouched.
 */
function starlightLlmsTxtWithoutIndex(opts) {
  const plugin = starlightLlmsTxt(opts);
  const originalSetup = plugin.hooks.setup;
  return {
    ...plugin,
    hooks: {
      ...plugin.hooks,
      setup(setupContext) {
        return originalSetup({
          ...setupContext,
          addIntegration(integration) {
            const configSetup = integration.hooks?.["astro:config:setup"];
            if (configSetup) {
              integration.hooks["astro:config:setup"] = (configContext) =>
                configSetup({
                  ...configContext,
                  injectRoute(route) {
                    if (route.pattern === "/llms.txt") return;
                    return configContext.injectRoute(route);
                  },
                });
            }
            return setupContext.addIntegration(integration);
          },
        });
      },
    },
  };
}

// https://astro.build/config
export default defineConfig({
  site: "https://docs.terragrunt.com",
  base: "/",
  output: "server",
  adapter: isVercel
    ? vercel({
      imageService: true,
      isr: {
        expiration: 60 * 60 * 24, // 24 hours
      },
      skewProtection: false,
    })
    : node({ mode: "standalone" }),
  integrations: [
    starlight({
      title: "Terragrunt",
      description: "Terragrunt is a flexible orchestration tool that allows Infrastructure as Code written in OpenTofu/Terraform to scale.",
      editLink: {
        baseUrl:
          "https://github.com/gruntwork-io/terragrunt/edit/main/docs",
      },
      customCss: ["./src/styles/global.css"],
      head: [
        {
          tag: 'meta',
          attrs: {
            name: 'twitter:card',
            content: 'summary_large_image',
          },
        },
        {
          tag: 'meta',
          attrs: {
            property: 'og:image',
            content: 'https://docs.terragrunt.com/images/terragrunt-og-image-1200x630.png',
          },
        },
        {
          tag: 'meta',
          attrs: {
            name: 'twitter:image',
            content: 'https://docs.terragrunt.com/images/terragrunt-twitter-image.png',
          },
        },
        {
          tag: 'script',
          attrs: {
            async: true,
            src: 'https://widget.kapa.ai/kapa-widget.bundle.js',
            'data-website-id': '925274e5-086f-446e-9108-64761bc7c4b4',
            'data-project-name': 'Terragrunt',
            'data-project-color': '#7B5AFF',
            'data-project-logo': 'https://docs.terragrunt.com/favicon.svg',
          },
        },
      ],
      components: {
        Header: "./src/components/Header.astro",
        PageSidebar: "./src/components/PageSidebar.astro",
        SiteTitle: "./src/components/SiteTitle.astro",
        SkipLink: "./src/components/SkipLink.astro",
      },
      logo: {
        dark: "/src/assets/horizontal-logo-light.svg",
        light: "/src/assets/horizontal-logo-dark.svg",
      },
      social: [
        {
          href: "/community/invite",
          icon: "discord",
          label: "Discord",
        },
      ],
      sidebar: sidebar,
      plugins: [
        starlightLinksValidator({
          exclude: [
            // Used in the docs for OpenTelemetry
            "http://localhost:16686/",
            "http://localhost:9090/",

            // Unfortunately, these have to be ignored, as they're referencing content
            // that is generated outside the contents of the markdown file.
            "/reference/cli/commands/run#*",
            "/reference/cli/commands/run/#*",
            "/reference/cli/commands/list#*",
            "/reference/cli/commands/list/#*",
            "/reference/cli/commands/find#*",
            "/reference/cli/commands/find/#*",

            // Custom .astro pages — can't be validated statically
            "/reference/experiments/active",
            "/reference/experiments/active#*",
            "/reference/experiments/completed",
            "/reference/experiments/completed#*",
            "/reference/strict-controls/active#*",
            "/reference/strict-controls/completed#*",
            "/process/changelog#*",
            "/process/changelog/*#*",

            // Used as redirects to the Terragrunt Discord server
            "/community/invite",
            "/tgs-discord",
          ],
        }),
        starlightLlmsTxtWithoutIndex()
      ],
    }),
    d2({
      // It's recommended that we just skip generation in Vercel,
      // and generate diagrams locally:
      // https://astro-d2.vercel.app/guides/how-astro-d2-works/#deployment
      skipGeneration: !!isVercel,
    }),
    partytown({
      config: {
        debug: false,
        logCalls: false,
        logGetters: false,
        logSetters: false,
        logImageRequests: false,
        logScriptExecution: false,
        logStackTraces: false,
        forward: ['dataLayer.push'],
      },
    }),
    sitemap({
      // changefreq/priority intentionally omitted: the Docusaurus/Astro
      // maintainers note these are ignored by Google's crawler, and Bing
      // treats them as advisory at best.
      //
      // lastmod intentionally omitted: a global new Date() stamps every URL
      // with build time, which Google heuristics discount as noise. Per-page
      // accuracy would need git log (Vercel's default shallow clone makes this
      // unreliable) or a populated `lastUpdated` frontmatter field.
    }),
  ],
  markdown: {
    // A custom `processor` still receives the integration-injected plugins (Starlight's syntax
    // highlighting, etc.) merged in automatically, so we only register our own rehype plugin here.
    processor: unified({ rehypePlugins: [rehypeChangelogAnchors] }),
  },
  // Note that some redirects are handled in vercel.json instead.
  //
  // This is because Astro won't do dynamic redirects for external destinations.
  // It's faster to have Vercel handle it anyways.
  redirects: {
    // Catch-all redirect from /docs/* to /*
    // Note: this only fires at depth 0 under the Vercel adapter; deeper paths
    // are handled by an equivalent rule in vercel.json. Kept here for `astro dev`.
    "/docs/[...slug]": "/[...slug]",

    // Root redirects
    "/": "/getting-started/quick-start/",
    "/docs/": "/getting-started/quick-start/",

    // Pages that have been rehomed.
    "/features/scaffold/": "/features/catalog/scaffold/",
    "/features/run-queue/": "/features/stacks/run-queue/",
    "/features/debugging/": "/troubleshooting/debugging/",
    "/upgrade/upgrading_to_terragrunt_0.19.x/": "/migrate/upgrading_to_terragrunt_0.19.x/",
    "/reference/terragrunt-cache/": "/features/units/terragrunt-cache/",
    "/reference/lock-files/": "/features/units/lock-files/",

    // Merged pages
    "/features/stacks/dependencies/": "/features/stacks/stack-operations/",
    "/features/stacks/orchestration/": "/features/stacks/stack-operations/",

    // Redirects to external sites.
    "/terragrunt-ambassador": "https://terragrunt.com/terragrunt-ambassador",
    "/terragrunt-scale": "/terragrunt-scale/overview/",
    "/contact/": "https://gruntwork.io/contact",
    "/commercial-support/": "https://gruntwork.io/support",
    "/cookie-policy/": "https://gruntwork.io/legal/cookie-policy/",

    // Restructured docs
    "/reference/configuration/": "/reference/hcl/",
    "/reference/cli-options/": "/reference/cli/",
    "/reference/built-in-functions/": "/reference/hcl/functions/",
    "/reference/config-blocks-and-attributes/": "/reference/hcl/blocks/",
    "/reference/strict-mode/": "/reference/strict-controls/",
    "/reference/log-formatting/": "/reference/logging/formatting/",
    "/features/aws-authentication/": "/features/units/authentication/",
    "/reference/experiment-mode/": "/reference/experiments/",

    // Support old doc structure paths
    "/getting-started/": "/getting-started/quick-start/",
    "/features/": "/features/units/",
    "/reference/": "/reference/hcl/",
    "/troubleshooting/": "/troubleshooting/debugging/",
    "/migrate/": "/migrate/migrating-from-root-terragrunt-hcl/",

    // Support old community paths
    "/community/": "/community/contributing/",
    "/support/": "/community/support/",

    // Support old feature paths
    "/features/inputs/": "/features/units/",
    "/features/locals/": "/features/units/",
    "/features/keep-your-terraform-code-dry/": "/features/units/",
    "/features/execute-terraform-commands-on-multiple-units-at-once/": "/features/stacks/",
    "/features/keep-your-terragrunt-architecture-dry/": "/features/units/includes/",
    "/features/keep-your-remote-state-configuration-dry/": "/features/units/state-backend/",
    "/features/keep-your-cli-flags-dry/": "/features/units/extra-arguments/",
    "/features/aws-auth/": "/features/units/authentication/",
    "/features/work-with-multiple-aws-accounts/": "/features/units/authentication/",
    "/features/auto-retry/": "/features/units/runtime-control/",
    "/features/provider-cache/": "/features/caching/provider-cache-server/",
    "/features/provider-caching/": "/features/caching/provider-cache-server/",
    "/features/engine/": "/features/units/engine/",
    "/features/run-report/": "/features/stacks/run-report/",
    "/features/provider-cache-server/": "/features/caching/provider-cache-server/",
    "/features/auto-provider-cache-dir/": "/features/caching/auto-provider-cache-dir/",
    "/features/cas/": "/features/caching/cas/",

    // Additional redirects for 404ing URLs
    "/features/execute-terraform-commands-on-multiple-modules-at-once/": "/features/stacks/",
    "/getting-started/configuration/": "/reference/hcl/",
    "/features/before-and-after-hooks/": "/features/units/hooks/",
    "/etting-started/configuration/": "/reference/hcl/", // typo in original URL
    "/features/log-formatting": "/reference/logging/formatting/",
    "/reference/lock-file-handling/": "/features/units/lock-files/",

    // Restructured docs
    "/reference/cli/rules": "/process/cli-rules/",

    // Unit features rehomed under /features/units/
    "/features/includes/": "/features/units/includes/",
    "/features/state-backend/": "/features/units/state-backend/",
    "/features/extra-arguments/": "/features/units/extra-arguments/",
    "/features/authentication/": "/features/units/authentication/",
    "/features/hooks/": "/features/units/hooks/",
    "/features/auto-init/": "/features/units/auto-init/",
    "/features/runtime-control/": "/features/units/runtime-control/",

    // Redirects for external resources
    "/community/invite": "https://discord.com/invite/YENaT9h8jh",
  },
  vite: {
    plugins: [
      tailwindcss(),
      {
        name: 'compatibility-query-redirect',
        configureServer(server) {
          server.middlewares.use((req, _res, next) => {
            const url = req.url ?? '';
            if (url === '/api/v1/compatibility' || url.startsWith('/api/v1/compatibility?')) {
              const qs = url.includes('?') ? url.split('?')[1] : '';
              const tool = new URLSearchParams(qs).get('tool');
              if (tool === 'opentofu' || tool === 'terraform') {
                req.url = `/api/v1/compatibility/${tool}`;
              } else {
                req.url = '/api/v1/compatibility/index';
              }
            }
            next();
          });
        },
      },
    ],
  },
});
