import { FilterPattern } from "@rollup/pluginutils";
import { Plugin, PluginContext } from "rollup";

//#region src/module/types.d.ts
/**
 * Duplicates Rollup's `ModuleInfo` interface for backwards compatibility
 */
interface ModuleInfo {
  id: string;
  importedIds: string[] | readonly string[];
  dynamicallyImportedIds: string[] | readonly string[];
}
//#endregion
//#region src/module/ModuleNode.d.ts
declare class ModuleNode {
  readonly id: string;
  readonly importedIds: readonly string[];
  readonly children: Set<ModuleNode>;
  constructor(moduleInfo: ModuleInfo);
}
//#endregion
//#region src/types.d.ts
type CircularDependenciesData = Record<string, Array<Array<ModuleNode['id']>>>;
/** Formatted output data produced by formatters */
type FormattedData = string | CircularDependenciesData | null | undefined;
/**
 * Metrics collected during circular dependency detection.
 * Provided in the `onEnd` callback for analysis and monitoring.
 */
interface Metrics {
  /** Total number of modules checked for circular dependencies */
  readonly modulesChecked: number;
  /** Number of unique cycles found */
  readonly cyclesFound: number;
  /** Size of the largest cycle (number of modules) */
  readonly largestCycleSize: number;
  /** Time taken for detection in milliseconds */
  readonly detectionTimeMs: number;
}
interface OptionsOnEndArgs {
  rawOutput: CircularDependenciesData;
  formattedOutput: unknown;
  metrics: Metrics;
}
interface Options {
  /**
   * Enable plugin
   *
   * @default true
   */
  enabled?: boolean;
  /**
   * Include specific files based on a RegExp or a glob pattern
   *
   * @default [/\.(c|m)?[jt]s(x)?$/]
   */
  include?: FilterPattern;
  /**
   * Exclude specific files based on a RegExp or a glob pattern
   *
   * @default [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/]
   */
  exclude?: FilterPattern;
  /**
   * Throw Rollup/Vite error instead of warning
   *
   * @default true
   */
  throwOnError?: boolean;
  /**
   * Path to the file with scan results. By default, the result is output to the console
   *
   * @default ""
   */
  outputFilePath?: string;
  /**
   * Enable debug logging for troubleshooting
   *
   * @default false
   */
  debug?: boolean;
  /**
   * Formats the output module path
   *
   * _Default_: `""`
   *
   * @param {string} path - The module path to be formatted
   * @returns {string} - The formatted module path
   */
  formatOutModulePath?: (path: string) => string;
  /**
   * Formats the given data into a specific output format
   *
   * _Default (console)_: `DefaultFormatters.Pretty({ colors: true })`
   *
   * _Default (file)_: `DefaultFormatters.JSON()`
   *
   * @param {CircularDependenciesData} data - The input data to be formatted
   * @returns {unknown} - The formatted output
   */
  formatOut?: (data: CircularDependenciesData) => unknown;
  /**
   * Filter function to ignore specific circular dependency cycles.
   * Return `true` to ignore the cycle, `false` to report it.
   *
   * @param {string[]} cyclePaths - Array of module paths forming the cycle
   * @returns {boolean} - Whether to ignore this cycle
   *
   * @example
   * ```ts
   * ignoreCycle: (paths) => paths.some(p => p.includes('generated'))
   * ```
   */
  ignoreCycle?: (cyclePaths: string[]) => boolean;
  /**
   * Called before the cycle detection starts
   *
   * @returns {void}
   */
  onStart?: (pluginContext: PluginContext) => void;
  /**
   * Called for each cyclical module
   *
   * @returns {void}
   */
  onDetected?: (modulePath: ModuleNode['id'], pluginContext: PluginContext) => void;
  /**
   * Called after the cycle detection ends
   *
   * @returns {void}
   */
  onEnd?: (params: OptionsOnEndArgs, pluginContext: PluginContext) => void;
}
//#endregion
//#region src/utils/formatters.d.ts
/** Formatter function that transforms circular dependencies data into a string */
type Formatter = (data: CircularDependenciesData) => string;
interface PrettyFormatterConfig {
  colors?: boolean;
}
/**
 * Creates a JSON formatter that serializes data with 2-space indentation.
 *
 * @returns Formatter function producing JSON string output
 *
 * @example
 * ```ts
 * circularDependencies({
 *   formatOut: DefaultFormatters.JSON()
 * })
 * ```
 */
declare function JSONFormatter(): Formatter;
/**
 * Creates a human-readable pretty formatter with optional color support.
 * Colors are enabled by default unless disabled via environment variables
 * (`NO_COLOR`, `NODE_DISABLE_COLORS`, `FORCE_COLOR=0`).
 *
 * @param config - Optional configuration for color output
 * @returns Formatter function producing styled string output
 *
 * @example
 * ```ts
 * circularDependencies({
 *   formatOut: DefaultFormatters.Pretty({ colors: false })
 * })
 * ```
 */
declare function PrettyFormatter(config?: PrettyFormatterConfig): Formatter;
declare const DefaultFormatters: {
  JSON: typeof JSONFormatter;
  Pretty: typeof PrettyFormatter;
};
//#endregion
//#region src/index.d.ts
/**
 * Creates a Rollup plugin that detects circular dependencies in your project.
 * Works with both Rollup and Vite.
 *
 * @param options - Plugin configuration options
 * @returns Rollup plugin instance
 *
 * @example
 * ```ts
 * // Basic usage
 *
 * import circularDependencies from 'rollup-plugin-circular-dependencies';
 *
 * export default {
 *   plugins: [circularDependencies()]
 * }
 * ```
 *
 * @example
 * ```ts
 * // Advanced usage
 *
 * import circularDependencies, { DefaultFormatters } from 'rollup-plugin-circular-dependencies';
 *
 * export default {
 *   plugins: [
 *     circularDependencies({
 *       enabled: true,
 *       exclude: [/node_modules/],
 *       throwOnError: true,
 *       debug: false,
 *       formatOut: DefaultFormatters.Pretty({ colors: false }),
 *       ignoreCycle: (paths) => paths.some(p => p.includes('generated')),
 *       onStart: (pluginContext) => {},
 *       onDetected: (modulePath, pluginContext) => {},
 *       onEnd: ({ rawOutput, formattedOutput, metrics }, pluginContext) => {
 *         console.log(`Found ${metrics.cyclesFound} cycle(s)`);
 *       },
 *     })
 *   ]
 * }
 * ```
 */
declare function circularDependencies(options?: Options): Plugin;
//#endregion
export { type CircularDependenciesData, DefaultFormatters, type FormattedData, type Metrics, type Options, circularDependencies, circularDependencies as default };