import path from 'node:path';
import js from '@eslint/js';
import { includeIgnoreFile } from '@eslint/compat';
import { defineConfig } from 'eslint/config';
import prettier from 'eslint-config-prettier';
import importX, { createNodeResolver } from 'eslint-plugin-import-x';
import htmlEslint from '@html-eslint/eslint-plugin';
import htmlParser from '@html-eslint/parser';
import defaultAttrs from './tools/build-icons/render/default-attrs.json' with { type: 'json' };
import tseslint from 'typescript-eslint';

const gitignorePath = path.join(import.meta.dirname, '.gitignore');

export default defineConfig([
  tseslint.configs.recommended,
  {
    // `packages/angular` has its own config with its own tsconfig, so a single `eslint .` run sees
    // two candidate roots and typescript-eslint refuses to guess between them.
    languageOptions: {
      parserOptions: {
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
  // Everything git ignores (generated icon sources, build output, caches) is ignored here too.
  includeIgnoreFile(gitignorePath),
  {
    // Ignores that are not in .gitignore, because these files are committed.
    ignores: [
      'lib',
      '**/tests',
      'packages/**/tests/*',
      'docs/images',
      'docs/**/examples/',
      'docs/.vitepress/theme/components/editors/preact/index.js',
      'packages/svelte/.svelte-kit',
      // Tracked in git despite matching a .gitignore pattern, so lint it.
      '!packages/lucide-react/dynamicIconImports.mjs',
    ],
  },
  {
    files: ['**/*.js'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      globals: {
        console: 'readonly',
        process: 'readonly',
        global: 'readonly',
        __dirname: 'readonly',
      },
    },
    plugins: {
      'import-x': importX,
    },
    settings: {
      'import-x/resolver-next': [createNodeResolver()],
    },
    rules: {
      ...js.configs.recommended.rules,
      ...prettier.rules,
      'no-console': 'off',
      'no-param-reassign': 'off',
      'no-shadow': 'off',
      'no-use-before-define': 'off',
      'import-x/no-extraneous-dependencies': [
        'error',
        {
          devDependencies: [
            '**/*.test.js',
            '**/*.spec.js',
            '**/scripts/**',
            'eslint.config.js',
            'packages/**/tests/**',
          ],
        },
      ],
      'import-x/extensions': [
        'error',
        {
          pattern: {
            mjs: 'always',
            json: 'always',
          },
        },
      ],
    },
  },
  {
    rules: {
      // Omitting a property by destructuring it away (`const { key, ...attrs } = node`) leaves the
      // omitted binding unused on purpose, so don't report it.
      '@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
    },
  },
  {
    files: ['./icons/*.svg'],
    languageOptions: {
      parser: htmlParser,
    },
    plugins: {
      '@html-eslint': htmlEslint,
    },
    rules: {
      '@html-eslint/require-doctype': 'off',
      '@html-eslint/no-duplicate-attrs': 'error',
      '@html-eslint/no-inline-styles': 'error',
      '@html-eslint/require-attrs': [
        'error',
        ...Object.entries(defaultAttrs).map(([attr, value]) => ({
          tag: 'svg',
          attr,
          value: String(value),
        })),
      ],
      '@html-eslint/indent': ['error', 2],
      '@html-eslint/no-multiple-empty-lines': ['error', { max: 0 }],
      '@html-eslint/no-extra-spacing-attrs': [
        'error',
        {
          enforceBeforeSelfClose: true,
        },
      ],
      '@html-eslint/attrs-newline': [
        'error',
        {
          inline: ['path', 'line', 'polyline', 'polygon', 'rect', 'circle', 'ellipse'],
        },
      ],
      '@html-eslint/require-closing-tags': [
        'error',
        {
          selfClosing: 'always',
          // Inside <svg> every tag counts as "foreign", where the rule only checks that a tag
          // already written `/>` stays that way. Listing the shapes here is what actually forces
          // `<path ...></path>` to become `<path ... />`.
          selfClosingCustomPatterns: ['^(path|line|polyline|polygon|rect|circle|ellipse)$'],
        },
      ],
      '@html-eslint/no-restricted-attr-values': [
        'error',
        {
          attrPatterns: ['^(fill|stroke)$'],
          attrValuePatterns: ['^(?!(none|currentColor)$).*$'],
          message:
            'Icons must inherit their colors: `fill` and `stroke` may only be `none` or `currentColor`.',
        },
      ],
      '@html-eslint/element-newline': 'error',
      '@html-eslint/no-trailing-spaces': 'error',
      '@html-eslint/quotes': 'error',
    },
  },
]);
