import {
  oxlintConfigMeta,
  type BuildFromOxlintConfigOptions,
  type EslintPluginOxlintConfig,
  type OxlintConfig,
} from './types.js';
import { handleRulesScope, readRulesFromConfig } from './rules.js';
import {
  defaultCategories,
  handleCategoriesScope,
  readCategoriesFromConfig,
} from './categories.js';
import { defaultPlugins, readPluginsFromConfig } from './plugins.js';
import { handleIgnorePatternsScope, readIgnorePatternsFromConfig } from './ignore-patterns.js';
import { handleOverridesScope, readOverridesFromConfig } from './overrides.js';
import { splitDisabledRulesForVueAstroAndSvelteFiles } from '../config-helper.js';
import {
  handleExtendsScope,
  readExtendsConfigsFromConfig,
  resolveRelativeExtendsPaths,
} from './extends.js';
import { getConfigContent } from './utilities.js';
import path from 'node:path';

/**
 * builds turned off rules, which are supported by oxlint.
 * It accepts an object similar to the .oxlintrc.json file.
 */
export const buildFromOxlintConfig = (
  config: OxlintConfig,
  options: BuildFromOxlintConfigOptions = {}
): EslintPluginOxlintConfig[] => {
  // if the option is not explicitly set but the config has typeAware enabled, we will enable it by default
  if (config.options?.typeAware === true && options.typeAware === undefined) {
    options.typeAware = true;
  }
  resolveRelativeExtendsPaths(config);

  const extendConfigs = readExtendsConfigsFromConfig(config);
  if (extendConfigs.length > 0) {
    handleExtendsScope(extendConfigs, config);
  }

  const rules: Record<string, 'off'> = {};
  const plugins = readPluginsFromConfig(config) ?? defaultPlugins;
  const categories = readCategoriesFromConfig(config) ?? defaultCategories;

  // it is not a plugin but it is activated by default
  plugins.push('eslint');

  // oxc handles "react-hooks" rules inside "react" plugin
  // our generator split them into own plugins
  if (plugins.includes('react')) {
    plugins.push('react-hooks');
  }

  handleCategoriesScope(plugins, categories, rules, options);

  const configRules = readRulesFromConfig(config);

  if (configRules !== undefined) {
    handleRulesScope(configRules, rules, options);
  }

  const baseConfig = {
    name: 'oxlint/from-oxlint-config',
    rules,
  };

  const overrides = readOverridesFromConfig(config);
  const configs = splitDisabledRulesForVueAstroAndSvelteFiles(
    baseConfig
  ) as EslintPluginOxlintConfig[];

  if (overrides !== undefined) {
    handleOverridesScope(overrides, configs, categories, options);
  }

  const ignorePatterns = readIgnorePatternsFromConfig(config);
  if (ignorePatterns === undefined) {
    return configs;
  } else {
    const ignoreConfig: EslintPluginOxlintConfig = {
      name: 'oxlint/oxlint-config-ignore-patterns',
    };
    handleIgnorePatternsScope(ignorePatterns, ignoreConfig);
    return [ignoreConfig, ...configs];
  }
};

/**
 * builds turned off rules, which are supported by oxlint.
 * It accepts an filepath to the .oxlintrc.json file.
 *
 * It the .oxlintrc.json file could not be found or parsed,
 * no rules will be deactivated and an error to `console.error` will be emitted
 */
export const buildFromOxlintConfigFile = (
  oxlintConfigFile: string,
  options: BuildFromOxlintConfigOptions = {}
): EslintPluginOxlintConfig[] => {
  const config = getConfigContent(oxlintConfigFile);

  // we could not parse form the file, do not build with default values
  // we can not be sure if the setup is right
  if (config === undefined) {
    return [];
  }

  config[oxlintConfigMeta] = {
    filePath: path.resolve(oxlintConfigFile),
  };

  return buildFromOxlintConfig(config, options);
};
