/* eslint-env node */
import process from "node:process";
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import prettier from "eslint-plugin-prettier";
import { FlatCompat } from "@eslint/eslintrc";
import path from "node:path";
import globals from "globals";

// Use FlatCompat to consume Next.js' legacy shareable configs under apps/portal
const compat = new FlatCompat({ baseDirectory: path.resolve("apps/portal") });

export default [
  // Global ignores
  {
    ignores: [
      "**/node_modules/**",
      "**/dist/**",
      "**/.next/**",
      "**/build/**",
      "**/coverage/**",
      "**/next-env.d.ts",
    ],
  },

  // Base JS recommendations for all files
  js.configs.recommended,

  // Prettier integration (warn-only)
  {
    plugins: { prettier },
    rules: {
      "prettier/prettier": "warn",
    },
  },

  // TypeScript (type-checked) for TS files only
  ...tseslint.configs.recommendedTypeChecked.map(config => ({
    ...config,
    files: ["**/*.ts", "**/*.tsx"],
    languageOptions: {
      ...(config.languageOptions || {}),
      globals: {
        ...globals.node,
      },
    },
  })),
  {
    files: [
      "apps/bff/**/*.ts",
      "packages/domain/**/*.ts",
      "packages/logging/**/*.ts",
      "packages/validation/**/*.ts",
    ],
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: process.cwd(),
      },
    },
    rules: {
      "@typescript-eslint/consistent-type-imports": "error",
      "@typescript-eslint/no-unused-vars": [
        "warn",
        { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
      ],
      "no-console": ["warn", { allow: ["warn", "error"] }],
    },
  },

  // Enforce consistent strict rules across shared as well
  {
    files: ["packages/**/*.{ts,tsx}"],
    rules: {
      "@typescript-eslint/no-redundant-type-constituents": "error",
      "@typescript-eslint/no-explicit-any": "error",
      "@typescript-eslint/no-unsafe-return": "error",
      "@typescript-eslint/no-unsafe-call": "error",
      "@typescript-eslint/no-unsafe-member-access": "error",
    },
  },

  // Next.js app: apply Next's recommended config; TS rules only on TS files
  ...compat
    .extends("next/core-web-vitals")
    .map(config => ({ ...config, files: ["apps/portal/**/*.{js,jsx,ts,tsx}"] })),
  ...compat
    .extends("next/typescript")
    .map(config => ({ ...config, files: ["apps/portal/**/*.{ts,tsx}"] })),

  // Ensure type-aware rules in portal have parser services
  {
    files: ["apps/portal/**/*.{ts,tsx}"],
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: process.cwd(),
      },
    },
    rules: {
      "@next/next/no-html-link-for-pages": "off",
    },
  },

  // Authenticated pages should rely on the shared route-group layout at (authenticated)/layout.tsx.
  {
    files: ["apps/portal/src/app/(authenticated)/**/*.{ts,tsx}"],
    rules: {
      // Prefer Next.js <Link> and router, forbid window/location hard reload in portal pages
      "no-restricted-syntax": [
        "error",
        {
          selector: "MemberExpression[object.name='window'][property.name='location']",
          message: "Use next/link or useRouter for navigation, not window.location.",
        },
        {
          selector:
            "MemberExpression[object.name='location'][property.name=/^(href|assign|replace)$/]",
          message: "Use next/link or useRouter for navigation, not location.*.",
        },
      ],
    },
  },
  // Allow the shared layout file itself to import the layout component
  {
    files: ["apps/portal/src/app/(authenticated)/layout.tsx"],
    rules: {
      "no-restricted-imports": "off",
    },
  },
  // Allow controlled window.location usage for invoice SSO download
  {
    files: ["apps/portal/src/app/(authenticated)/billing/invoices/[id]/page.tsx"],
    rules: {
      "no-restricted-syntax": "off",
    },
  },

  // Enforce layered type system architecture
  {
    files: ["apps/portal/src/**/*.{ts,tsx}", "apps/bff/src/**/*.ts"],
    rules: {
      "no-restricted-imports": [
        "error",
        {
          patterns: [
            {
              group: ["@customer-portal/domain/**/src/**"],
              message:
                "Don't import from domain package internals. Use @customer-portal/domain/<domain> or its Providers namespace instead.",
            },
            {
              group: ["**/utils/ui-state*"],
              message:
                "ui-state.ts has been removed. Use patterns from @customer-portal/domain instead.",
            },
            {
              group: ["@/types"],
              message:
                "Avoid importing from @/types. Import types directly from @customer-portal/domain/<domain> or define locally.",
            },
          ],
        },
      ],
      // Prevent defining deprecated type patterns
      "no-restricted-syntax": [
        "error",
        {
          selector:
            "TSInterfaceDeclaration[id.name=/^(LegacyAsyncState|PaginatedState|FilteredState)$/]",
          message:
            "These legacy state types are deprecated. Use AsyncState, PaginatedAsyncState, or FilterState from @customer-portal/domain instead.",
        },
        {
          selector:
            "TSTypeAliasDeclaration[id.name=/^(LegacyAsyncState|PaginatedState|FilteredState)$/]",
          message:
            "These legacy state types are deprecated. Use AsyncState, PaginatedAsyncState, or FilterState from @customer-portal/domain instead.",
        },
      ],
    },
  },

  // Node globals for Next config file
  {
    files: ["apps/portal/next.config.mjs"],
    languageOptions: {
      globals: {
        ...globals.node,
      },
    },
  },

  // BFF: strict rules enforced + prevent domain type duplication
  {
    files: ["apps/bff/**/*.ts"],
    rules: {
      "@typescript-eslint/no-explicit-any": "error",
      "@typescript-eslint/no-unsafe-assignment": "error",
      "@typescript-eslint/no-unsafe-member-access": "error",
      "@typescript-eslint/no-unsafe-call": "error",
      "@typescript-eslint/no-unsafe-return": "error",
      "@typescript-eslint/no-unsafe-argument": "error",
      "@typescript-eslint/require-await": "error",
      "@typescript-eslint/no-floating-promises": "error",
      "no-restricted-syntax": [
        "error",
        {
          selector:
            "TSInterfaceDeclaration[id.name=/^(Invoice|InvoiceItem|Subscription|PaymentMethod|SimDetails)$/]",
          message:
            "Don't re-declare domain types in application code. Import from @customer-portal/domain/<domain> instead.",
        },
        {
          selector:
            "TSTypeAliasDeclaration[id.name=/^(Invoice|InvoiceItem|Subscription|PaymentMethod|SimDetails)$/]",
          message:
            "Don't re-declare domain types in application code. Import from @customer-portal/domain/<domain> instead.",
        },
      ],
    },
  },

  // Integration packages: must use domain providers and avoid legacy packages
  {
    files: ["packages/integrations/**/src/**/*.ts"],
    rules: {
      "no-restricted-imports": [
        "error",
        {
          patterns: [
            {
              group: ["@customer-portal/contracts", "@customer-portal/contracts/*", "@customer-portal/schemas", "@customer-portal/schemas/*"],
              message:
                "Legacy contracts/schemas packages have been removed. Import from @customer-portal/domain/<domain>/providers instead.",
            },
          ],
        },
      ],
    },
  },
];
