import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
import vueTsEslintConfig from '@vue/eslint-config-typescript';
import unocss from '@unocss/eslint-config/flat';
import eslint from '@eslint/js';
import pluginVitest from '@vitest/eslint-plugin';
import pluginCypress from 'eslint-plugin-cypress/flat';
import pluginImport from 'eslint-plugin-import';
import pluginJsonc from 'eslint-plugin-jsonc';
import pluginSimpleImportSort from 'eslint-plugin-simple-import-sort';
import pluginVue from 'eslint-plugin-vue';
import globals from 'globals';
import jsoncParser from 'jsonc-eslint-parser';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  {
    name: 'app/files-to-lint',
    files: ['**/*.{ts,mts,tsx,vue}'],
  },

  {
    name: 'app/files-to-ignore',
    ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**', '**/*.json', '!src/i18n/locales/*.json'],
  },

  {
    languageOptions: {
      globals: {
        ...globals.browser,
        ...globals.commonjs,
        ...globals.node,
      },
    },
  },

  eslint.configs.recommended,
  ...pluginJsonc.configs['flat/recommended-with-json'],
  ...pluginJsonc.configs['flat/prettier'],
  ...pluginVue.configs['flat/essential'],
  ...vueTsEslintConfig(),
  skipFormatting,
  unocss,

  {
    ...pluginVitest.configs.recommended,
    files: ['src/**/__tests__/*'],
  },

  {
    ...pluginCypress.configs.recommended,
    files: ['cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}', 'cypress/support/**/*.{js,ts,jsx,tsx}'],
  },

  // import rules
  {
    files: ['**/*.{js,mjs,cjs,jsx,ts,tsx,vue}'],
    extends: [pluginImport.flatConfigs.recommended, pluginImport.flatConfigs.typescript],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
    },
    rules: {
      'import/no-deprecated': 'error',
      'import/no-empty-named-blocks': 'error',
      'import/no-mutable-exports': 'error',
      'import/no-named-as-default': 'error',
      'import/no-named-as-default-member': 'error',
      'import/no-absolute-path': 'error',
      'import/no-dynamic-require': 'error',
      'import/no-self-import': 'error',
      'import/no-unresolved': 'off',
      'import/no-useless-path-segments': [
        'error',
        {
          noUselessIndex: true,
        },
      ],
      'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
      'import/exports-last': 'error',
      'import/first': 'error',
      'import/newline-after-import': [
        'error',
        {
          count: 1,
          considerComments: true,
        },
      ],
      'import/no-anonymous-default-export': 'error',
      'import/no-duplicates': 'error',
      'import/no-named-default': 'error',
      'import/no-unassigned-import': [
        'error',
        {
          allow: ['**/*.{css,scss}', '**/styles', 'dayjs/locale/*'],
        },
      ],
    },
  },

  // sort rules
  {
    plugins: {
      'simple-import-sort': pluginSimpleImportSort,
    },
    rules: {
      'simple-import-sort/imports': [
        'error',
        {
          groups: [
            // Packages. `vue` related packages come first.
            ['^vue', '^@vue', 'pinia', '^vite$', '^@vitejs', '^vite-plugin', '^unocss$', '^@unocss', '^@?\\w'],
            // Node.js builtins.
            ['^node:'],
            // Internal packages.
            [
              '^@/layout(/.*|$)',
              '^@/views(/.*|$)',
              '^@/components(/.*|$)',
              '^@/transitions(/.*|$)',
              '^@/hooks(/.*|$)',
              '^@/directives(/.*|$)',
              '^@/stores(/.*|$)',
              '^@/router(/.*|$)',
              '^@/i18n(/.*|$)',
              '^@/api(/.*|$)',
              '^@/utils(/.*|$)',
              '^@/constants(/.*|$)',
              '^@/icons(/.*|$)',
              '^@/styles(/.*|$)',
            ],
            // Assets
            ['^@/assets(/.*|$)'],
            // Parent imports. Put `..` last.
            ['^\\.\\.(?!/?$)', '^\\.\\./?$'],
            // Other relative imports. Put same-folder imports and `.` last.
            ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
            // Type imports
            [
              '^vue.*\\u0000$',
              '^@vue.*\\u0000$',
              '^pinia.*\\u0000$',
              '^vite\\u0000$',
              '^@vitejs.*\\u0000$',
              '^vite-plugin.*\\u0000$',
              '^unocss\\u0000$',
              '^@unocss.*\\u0000$',
              '^@?\\w.*\\u0000$',
              '^node:.*\\u0000$',
              '^@/constants.*\\u0000$',
              '^@/types.*\\u0000$',
              '^.*\\u0000$',
            ],
            // Style imports.
            ['^.+\\.s?css$'],
            // Side effect imports.
            ['^\\u0000'],
          ],
        },
      ],
      'simple-import-sort/exports': 'error',
    },
  },

  // json rules
  {
    files: ['**/*.json'],
    languageOptions: {
      parser: jsoncParser,
    },
    rules: {
      'jsonc/key-name-casing': [
        'error',
        {
          camelCase: true,
        },
      ],
      'jsonc/sort-keys': [
        'error',
        {
          pathPattern: '.*',
          order: { type: 'asc' },
        },
      ],
    },
  },

  // js rules
  {
    files: ['**/*.{js,mjs,cjs,jsx,vue}'],
    rules: {
      'object-shorthand': ['error', 'always'],
      'no-unused-vars': 'off',
      'no-var': 'error',
    },
  },

  // ts rules
  {
    files: ['**/*.{ts,mts,tsx,vue}'],
    rules: {
      'object-shorthand': ['error', 'always'],
      '@typescript-eslint/no-unused-vars': 'error',
      '@typescript-eslint/no-explicit-any': 'error',
      '@typescript-eslint/no-inferrable-types': 'off',
      '@typescript-eslint/prefer-optional-chain': 'off',
    },
  },

  // vue rules
  {
    files: ['**/*.vue'],
    rules: {
      'vue/component-tags-order': [
        'error',
        {
          order: ['script:not([setup])', 'script[setup]', 'template', 'style:not([scoped])', 'style[scoped]'],
        },
      ],
      'vue/component-name-in-template-casing': [
        'error',
        'PascalCase',
        {
          registeredComponentsOnly: false,
          ignores: ['/^un-/'],
        },
      ],
      'vue/multi-word-component-names': [
        'error',
        {
          ignores: ['Login'],
        },
      ],
      'vue/html-self-closing': [
        'error',
        {
          html: {
            void: 'always',
            normal: 'never',
            component: 'always',
          },
          svg: 'always',
          math: 'always',
        },
      ],
      'vue/prop-name-casing': ['error', 'camelCase'],
      'vue/attribute-hyphenation': [
        'error',
        'always',
        {
          ignore: [],
        },
      ],
      'vue/padding-line-between-blocks': ['error', 'always'],
      'vue/block-lang': [
        'error',
        {
          script: {
            lang: 'ts',
          },
          template: {},
          style: {
            lang: 'scss',
          },
        },
      ],
      'vue/no-mutating-props': [
        'error',
        {
          shallowOnly: true,
        },
      ],
    },
  },
);
