/* eslint-disable @typescript-eslint/no-namespace */

import { ESLint } from 'eslint';
import useAtYourOwnRisk from 'eslint/use-at-your-own-risk';

import type { ClassicConfig } from '../Config';
import type { Linter } from '../Linter';
import type * as Shared from './ESLintShared';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
declare class LegacyESLintBase extends Shared.ESLintBase<
  ClassicConfig.Config,
  LegacyESLint.ESLintOptions
> {
  static readonly configType: 'eslintrc';
}

function throwMissingLegacyESLintError(): never {
  throw new Error(
    'LegacyESLint is not available with the current version of ESLint.',
  );
}

/* eslint-disable-next-line @typescript-eslint/no-extraneous-class */
class MissingLegacyESLint {
  static readonly configType = 'eslintrc';
  static readonly version = (ESLint as typeof LegacyESLintBase).version;
  constructor() {
    throwMissingLegacyESLintError();
  }
  static getErrorResults(): Shared.LintResult {
    throwMissingLegacyESLintError();
  }
  static outputFixes(): Promise<void> {
    throwMissingLegacyESLintError();
  }
}

/**
 * The ESLint class is the primary class to use in Node.js applications.
 * This class depends on the Node.js fs module and the file system, so you cannot use it in browsers.
 *
 * If you want to lint code on browsers, use the Linter class instead.
 */
export class LegacyESLint extends ((useAtYourOwnRisk.LegacyESLint ??
  MissingLegacyESLint) as typeof LegacyESLintBase) {}
export namespace LegacyESLint {
  export interface ESLintOptions extends Shared.ESLintOptions<ClassicConfig.Config> {
    /**
     * If you pass directory paths to the eslint.lintFiles() method, ESLint checks the files in those directories that
     * have the given extensions. For example, when passing the src/ directory and extensions is [".js", ".ts"], ESLint
     * will lint *.js and *.ts files in src/. If extensions is null, ESLint checks *.js files and files that match
     * overrides[].files patterns in your configuration.
     * Note: This option only applies when you pass directory paths to the eslint.lintFiles() method.
     * If you pass glob patterns, ESLint will lint all files matching the glob pattern regardless of extension.
     */
    extensions?: string[] | null;
    /**
     * If false is present, the eslint.lintFiles() method doesn't respect `.eslintignore` files in your configuration.
     * @default true
     */
    ignore?: boolean;
    /**
     * The path to a file ESLint uses instead of `$CWD/.eslintignore`.
     * If a path is present and the file doesn't exist, this constructor will throw an error.
     */
    ignorePath?: string;
    /**
     * The path to a configuration file, overrides all configurations used with this instance.
     * The options.overrideConfig option is applied after this option is applied.
     */
    overrideConfigFile?: string | null;
    /**
     * The severity to report unused eslint-disable directives.
     * If this option is a severity, it overrides the reportUnusedDisableDirectives setting in your configurations.
     */
    reportUnusedDisableDirectives?: Linter.SeverityString | null;
    /**
     * The path to a directory where plugins should be resolved from.
     * If null is present, ESLint loads plugins from the location of the configuration file that contains the plugin
     * setting.
     * If a path is present, ESLint loads all plugins from there.
     */
    resolvePluginsRelativeTo?: string | null;
    /**
     * An array of paths to directories to load custom rules from.
     */
    rulePaths?: string[];
    /**
     * If false is present, ESLint doesn't load configuration files (.eslintrc.* files).
     * Only the configuration of the constructor options is valid.
     */
    useEslintrc?: boolean;
  }
  export type DeprecatedRuleInfo = Shared.DeprecatedRuleInfo;
  export type EditInfo = Shared.EditInfo;
  export type Formatter = Shared.Formatter;
  export type LintMessage = Shared.LintMessage;
  export type LintResult = Omit<Shared.LintResult, 'stats'>;
  export type LintTextOptions = Shared.LintTextOptions;
  export type SuppressedLintMessage = Shared.SuppressedLintMessage;
}
