import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import pluginVue from 'eslint-plugin-vue';
import vueTsEslintConfig from '@vue/eslint-config-typescript';
import tsParser from '@typescript-eslint/parser';
import stylistic from '@stylistic/eslint-plugin';
import prettier from 'eslint-config-prettier';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

export default [
  {
    name: 'app/files-to-lint',
    files: ['**/*.{ts,mts,tsx,vue}'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        projectService: {
          defaultProject: resolve(__dirname, 'tsconfig.app.json'),
        },
        tsconfigRootDir: __dirname,
        sourceType: 'module',
        ecmaVersion: 'latest',
        allowDefaultProject: true,
      },
    },
    plugins: {
      '@stylistic': stylistic,
    },
  },

  {
    name: 'app/files-to-ignore',
    ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**', '**/node_modules/**', '**/.ponder/**', '**/__tests__/**'],
  },

  ...pluginVue.configs['flat/essential'],
  ...vueTsEslintConfig(),

  {
    name: 'app/custom-rules',
    rules: {
      // TypeScript rules
      '@typescript-eslint/no-explicit-any': 'error',
      '@typescript-eslint/no-unused-vars': [
        'error',
        {
          argsIgnorePattern: '^_',
          varsIgnorePattern: '^_',
          caughtErrorsIgnorePattern: '^_',
        },
      ],

      // General code quality
      'no-console': 'error',
      '@stylistic/indent': ['error', 2, { SwitchCase: 1 }],
      'max-len': ['error', { code: 140 }],

      // Vue specific rules
      'vue/multi-word-component-names': 'error',
      'vue/component-name-in-template-casing': ['error', 'PascalCase'],
      'vue/require-prop-types': 'error',
      'vue/require-default-prop': 'error',
      'vue/html-indent': ['error', 2],
      'vue/no-unused-vars': 'error',

      // Disable rules that conflict with Prettier
      'vue/max-attributes-per-line': 'off',
      'vue/singleline-html-element-content-newline': 'off',
      'vue/html-self-closing': 'off',

      // Naming conventions
      camelcase: ['error', { properties: 'never', ignoreDestructuring: true, allow: ['^UNSAFE_'] }],

      // Complexity rules (disabled as per requirements)
      complexity: 'off',
      'max-depth': 'off',
      'max-lines': 'off',
      'max-params': 'off',
    },
  },

  {
    name: 'arch/graphql-no-interpolation',
    rules: {
      'no-restricted-syntax': [
        'error',
        {
          selector:
            "Property[key.name='query'] > TemplateLiteral[expressions.length>0], Property[key.name='mutation'] > TemplateLiteral[expressions.length>0]",
          message:
            'String interpolation used in a GraphQL query or mutation string. GraphQL queries must not use string interpolation — it bypasses type-checking and is unsafe. Use the `variables` parameter in the fetch body instead. Example: `variables: { holder: address }`. See PR #191 for the pattern.',
        },
        {
          selector: "CallExpression[callee.property.name='waitForTimeout']",
          message:
            '[BANNED] waitForTimeout is a fixed delay. → Subscribe to events instead (eth_newFilter for on-chain, waitForSelector/waitForURL for DOM). → Polling with timeout is acceptable only if no event source exists. → See AGENTS.md #Engineering Principles.',
        },
        {
          selector:
            "NewExpression[callee.name='Promise'] > ArrowFunctionExpression CallExpression[callee.name='setTimeout']",
          message:
            '[BANNED] Promise+setTimeout sleep pattern. → Use event subscription or polling with timeout instead. → See AGENTS.md #Engineering Principles.',
        },
      ],
    },
  },

  {
    name: 'app/tests-override',
    files: ['src/**/__tests__/**/*.ts', 'src/**/__tests__/**/*.tsx'],
    languageOptions: {
      parserOptions: {
        projectService: false,
        project: undefined,
      },
    },
  },

  prettier,
];
