import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import tseslint from "typescript-eslint";
import turboPlugin from "eslint-plugin-turbo";
import boundaries from "eslint-plugin-boundaries";
import globals from "globals";
import conformancePlugin from "./plugin.js";
import path from "node:path";
import { fileURLToPath } from "node:url";
// <gen:realtime-rules-imports>

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(__dirname, "..", "..");

export default [
  { ignores: ["dist/**", "node_modules/**", ".next/**", ".turbo/**", "storybook-static/**"] },
  js.configs.recommended,
  {
    files: ["**/*.{mjs,cjs,js}", "**/*.config.{ts,tsx}"],
    languageOptions: {
      globals: { ...globals.node },
    },
  },
  ...tseslint.configs.recommended,
  eslintConfigPrettier,
  {
    plugins: { turbo: turboPlugin },
    rules: {
      "turbo/no-undeclared-env-vars": "warn",
    },
  },
  {
    plugins: { conformance: conformancePlugin },
    rules: {
      // Structural conformance rules (milestone iii.a).
      // All 5 features now have manifests; promoted to ERROR.
      "conformance/feature-must-have-manifest": [
        "error",
        { repoRoot },
      ],
      "conformance/usecase-must-have-test-file": "error",
      "conformance/required-cores-installed": [
        "error",
        { repoRoot },
      ],
      "conformance/no-undeclared-event-publish": ["warn", { repoRoot }],
      "conformance/no-undeclared-audit": ["warn", { repoRoot }],
      "conformance/component-must-have-story": "warn",
      "conformance/component-must-have-test": "warn",
      "conformance/atomic-tier-import-direction": "warn",
    },
  },
  {
    rules: {
      // Honour the leading-underscore convention for intentionally-unused params/vars.
      "@typescript-eslint/no-unused-vars": [
        "error",
        {
          argsIgnorePattern: "^_",
          varsIgnorePattern: "^_",
          caughtErrorsIgnorePattern: "^_",
        },
      ],
    },
  },
  {
    plugins: { boundaries },
    settings: {
      "boundaries/elements": [
        { type: "app", pattern: "apps/*" },
        { type: "tooling", pattern: "packages/core-eslint" },
        { type: "tooling", pattern: "packages/core-typescript" },
        { type: "tooling", pattern: "packages/core-testing" },
        { type: "core-composition", pattern: "packages/core-api" },
        { type: "core-composition", pattern: "packages/core-cms" },
        { type: "core", pattern: "packages/core-*" },
        { type: "feature", pattern: "packages/!(core-*)" },
      ],
    },
    rules: {
      "boundaries/element-types": [
        2,
        {
          default: "disallow",
          rules: [
            { from: "app", allow: ["app", "core", "core-composition", "feature", "tooling"] },
            { from: "feature", allow: ["core", "tooling"] },
            { from: "core", allow: ["core", "tooling"] },
            { from: "core-composition", allow: ["core", "feature", "tooling"] },
            { from: "tooling", allow: ["tooling"] },
          ],
        },
      ],
    },
  },
  // R40 — block direct @sentry/* imports outside the allowlisted instrumentation paths
  {
    files: ["**/*.{ts,tsx,mjs,cjs,js}"],
    rules: {
      "no-restricted-imports": [
        "error",
        {
          patterns: [
            {
              group: ["@sentry/*"],
              message:
                "Import from @repo/core-shared/instrumentation instead — feature packages must not depend on Sentry directly (R40).",
            },
          ],
        },
      ],
    },
  },
  // R40 allowlist — the only paths permitted to import @sentry/*.
  // After the OTel migration (ADR-017): server-side Sentry SDK usage is limited to
  // the OTel bridge + browser/client init files. The @sentry/* ESLint restriction
  // stays; the allowlist is narrowed from the original "**/instrumentation/sentry/**".
  // Patterns are double-star prefixed so they match whether eslint runs from
  // the repo root or from inside a sub-package.
  {
    files: [
      // OTel bridge — the only server-side file that may import @sentry/opentelemetry
      "**/instrumentation/otel/sentry-bridge.{ts,js}",
      "**/instrumentation/otel/sentry-bridge.test.{ts,js}",
      // OTel DI binder — may import @sentry/opentelemetry via sentry-bridge
      "**/instrumentation/di/bind-otel-instrumentation.{ts,js}",
      "**/instrumentation/di/bind-otel-instrumentation.test.{ts,js}",
      // Browser-side Sentry init helpers (server-only migration — browser keeps Sentry SDK directly)
      "**/instrumentation/sentry/init-client.{ts,js}",
      "**/instrumentation/sentry/init-client.test.{ts,js}",
      "**/instrumentation/sentry/init-client-react.{ts,js}",
      "**/instrumentation/sentry/init-client-react.test.{ts,js}",
      // Server-side Sentry SDK init still used by apps (calls Sentry.init with DSN)
      "**/instrumentation/sentry/init-server.{ts,js}",
      "**/instrumentation/sentry/init-server.test.{ts,js}",
      "**/instrumentation/sentry/init-server-node.{ts,js}",
      "**/instrumentation/sentry/init-server-node.test.{ts,js}",
      // Test guard — mocks Sentry + OTel SDKs to prevent real init in test processes
      "**/setup/no-instrumentation.{ts,js}",
      "**/setup/no-instrumentation.test.{ts,js}",
      // Legacy alias for one release cycle
      "**/setup/no-sentry.{ts,js}",
      "**/setup/no-sentry.test.{ts,js}",
      // App-level instrumentation entry points and build config
      "**/instrumentation.{ts,js,mjs}",
      "**/instrumentation-client.{ts,js,mjs}",
      "**/next.config.{mjs,ts,js}",
      "**/vite.config.{ts,mjs,js}",
      "**/sentry.*.config.{ts,mjs,js}",
    ],
    rules: {
      "no-restricted-imports": "off",
    },
  },
  // R52 — OTel SDK packages (@opentelemetry/sdk-*, @opentelemetry/resources,
  // @opentelemetry/semantic-conventions, @opentelemetry/instrumentation-*,
  // @sentry/opentelemetry) are restricted to core-shared/instrumentation/otel/
  // and app-level init paths.
  // The vendor-neutral API packages (@opentelemetry/api, @opentelemetry/api-logs)
  // are unrestricted within core-shared/instrumentation/ — features use them for
  // advanced tracing without coupling to the SDK.
  {
    files: [
      "**/instrumentation/otel/**/*.{ts,tsx,mjs,cjs,js}",
      // App-level init and build config also allowed to import OTel SDK packages
      "**/instrumentation.{ts,js,mjs}",
      "**/next.config.{mjs,ts,js}",
      "**/vite.config.{ts,mjs,js}",
    ],
    rules: {
      "no-restricted-imports": "off",
    },
  },
  // E1 — Event handlers must not be re-exported. Wire them only inside the
  // consumer feature's bind-production / bind-dev-seed (spec § 2.2 Rule E1).
  // J  — Direct `payload.jobs.*` access is forbidden outside the integration
  // layer. Use IJobQueue (from @repo/core-shared/jobs) instead.
  // Events + jobs rules are added here when @repo/core-events is scaffolded
  // via `pnpm turbo gen core-package events`.
  // <gen:events-rules>
  // R2 / R1 (ADR-016) — realtime-specific ESLint rules (no-direct-socket-io,
  // no-realtime-handler-reexport) are added here when @repo/core-realtime is
  // scaffolded via `pnpm turbo gen core-package realtime`.
  // <gen:realtime-rules>
];
