/**
 * Canonical Sentry wiring snippets the AI should drop into any
 * new app it scaffolds. Keeping these in one place (and naming
 * the file paths explicitly) means the AI's outputs are
 * deterministic across chats — every Next.js app it scaffolds
 * gets the same instrumentation files, the same global error
 * boundary, and the same `withSentryConfig` wrapper.
 *
 * The runtime env vars `NEXT_PUBLIC_SENTRY_DSN` and
 * `SENTRY_AUTH_TOKEN` are guaranteed to exist on every Coolify
 * app created via apps.create with a `projectId` — see
 * `lib/integrations/sentry.ts` and `applyEnvsAndDeploy` in
 * `app/api/mcp/route.ts`.
 *
 * The AI references these via `getSentrySnippets("nextjs")` etc.
 * Authoring rule: when changing any snippet, also bump the
 * matching file in vibn-frontend itself so they stay in sync —
 * vibn-frontend is the reference implementation.
 */

export type SentryFramework = 'nextjs' | 'vite-react';

export interface SentrySnippet {
  /** Repo-relative path the file should land at. */
  path: string;
  /** File contents, copied verbatim by the AI. */
  contents: string;
  /** Short description for AI to mention to the user, if relevant. */
  purpose: string;
}

export interface SentryWiringPackage {
  framework: SentryFramework;
  /** npm dependencies the AI must add to package.json. */
  dependencies: string[];
  /** Files to write into the project. */
  files: SentrySnippet[];
  /** Free-form modifications the AI must apply to existing files. */
  modifications: string[];
}

/**
 * Returns the full set of files + dependency edits + free-form
 * modifications the AI must apply when scaffolding a new app of
 * this framework. Currently covers Next.js (App Router) and
 * Vite + React.
 */
export function getSentrySnippets(framework: SentryFramework): SentryWiringPackage {
  switch (framework) {
    case 'nextjs':
      return NEXTJS_PACKAGE;
    case 'vite-react':
      return VITE_REACT_PACKAGE;
    default: {
      const exhaustive: never = framework;
      throw new Error(`Unsupported Sentry framework: ${exhaustive}`);
    }
  }
}

// ──────────────────────────────────────────────────────────────────
// Next.js (App Router, Next 14+)
// ──────────────────────────────────────────────────────────────────

const NEXTJS_PACKAGE: SentryWiringPackage = {
  framework: 'nextjs',
  dependencies: ['@sentry/nextjs'],
  files: [
    {
      path: 'instrumentation.ts',
      purpose: 'Server + edge runtime Sentry init',
      contents: `import * as Sentry from '@sentry/nextjs';

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    Sentry.init({
      dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
      tracesSampleRate: 1.0,
      enabled: Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN),
      environment: process.env.SENTRY_ENVIRONMENT || process.env.NODE_ENV,
    });
  }
  if (process.env.NEXT_RUNTIME === 'edge') {
    Sentry.init({
      dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
      tracesSampleRate: 1.0,
      enabled: Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN),
      environment: process.env.SENTRY_ENVIRONMENT || process.env.NODE_ENV,
    });
  }
}

export const onRequestError = Sentry.captureRequestError;
`,
    },
    {
      path: 'instrumentation-client.ts',
      purpose: 'Browser Sentry init with Session Replay',
      contents: `import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  enabled: Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN),
  environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || process.env.NODE_ENV,
  tracesSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    Sentry.replayIntegration({
      maskAllText: true,
      blockAllMedia: true,
    }),
  ],
});

export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
`,
    },
    {
      path: 'app/global-error.tsx',
      purpose: 'Catches root-layout crashes that escape every other error boundary',
      contents: `"use client";

import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";

export default function GlobalError({
  error,
}: {
  error: Error & { digest?: string };
}) {
  useEffect(() => {
    Sentry.captureException(error);
  }, [error]);

  return (
    <html>
      <body>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", minHeight: "100vh", padding: "2rem", fontFamily: "system-ui, sans-serif" }}>
          <h1 style={{ fontSize: "1.5rem", marginBottom: "0.5rem" }}>Something went wrong</h1>
          <p style={{ color: "#666" }}>We&apos;ve been notified. Try refreshing.</p>
          {error.digest ? <code style={{ fontSize: "0.75rem", color: "#999", marginTop: "1rem" }}>ref: {error.digest}</code> : null}
        </div>
      </body>
    </html>
  );
}
`,
    },
  ],
  modifications: [
    'In next.config.ts (or next.config.js), import withSentryConfig from "@sentry/nextjs" and wrap the exported config with withSentryConfig(nextConfig, { org: "vibnai", project: "<sentry-project-slug>", silent: !process.env.CI, widenClientFileUpload: true, tunnelRoute: "/monitoring", telemetry: false, errorHandler: (err) => console.warn("Sentry source map upload skipped:", err.message) }).',
    'In Dockerfile (if the project uses Docker), add ARG NEXT_PUBLIC_SENTRY_DSN and ARG SENTRY_AUTH_TOKEN in the builder stage, then ENV NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN and ENV SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN — without these the build args from Coolify never reach `next build`.',
    'The Sentry project slug for this Vibn project is fs_projects.data.sentry.slug — fetch it from the projects/get MCP tool and substitute into the next.config.ts above.',
  ],
};

// ──────────────────────────────────────────────────────────────────
// Vite + React
// ──────────────────────────────────────────────────────────────────

const VITE_REACT_PACKAGE: SentryWiringPackage = {
  framework: 'vite-react',
  dependencies: ['@sentry/react', '@sentry/vite-plugin'],
  files: [
    {
      path: 'src/sentry.ts',
      purpose: 'Sentry init, imported once at the top of main.tsx',
      contents: `import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: import.meta.env.VITE_SENTRY_DSN,
  enabled: Boolean(import.meta.env.VITE_SENTRY_DSN),
  environment: import.meta.env.MODE,
  tracesSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration({ maskAllText: true, blockAllMedia: true }),
  ],
});
`,
    },
  ],
  modifications: [
    'In src/main.tsx, add `import "./sentry"` as the FIRST import line (before React, before App).',
    'In vite.config.ts, add the Sentry vite plugin: import { sentryVitePlugin } from "@sentry/vite-plugin"; then in plugins: [sentryVitePlugin({ org: "vibnai", project: "<sentry-project-slug>", authToken: process.env.SENTRY_AUTH_TOKEN, telemetry: false, errorHandler: (err) => console.warn(err.message) })]. Set build.sourcemap = true so source maps generate.',
    'Vite uses VITE_SENTRY_DSN (not NEXT_PUBLIC_SENTRY_DSN). Add `VITE_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN` as a Coolify env var alias on the app, OR have the AI rename the env when injecting via apps_create.',
    'Wrap the root <App /> in <Sentry.ErrorBoundary fallback={<p>Something broke</p>}><App /></Sentry.ErrorBoundary> so React render errors propagate to Sentry.',
  ],
};
