import { Options } from 'prettier';

/**
 * Add any missing dependency to package.json content.
 * @param current Current package.json content
 * @param updates Updates to apply
 * @return Object with new content if changed and null otherwise
 * @example
 * addPackageJsonDependencies({}, { dependencies: { a: '^1.2.3' } });
 * // { dependencies: { a: '^1.2.3' } }
 * addPackageJsonDependencies({ dependencies: { a: '^1.2.3' } }, { dependencies: { a: '^1.2.0' } });
 * // null
 * addPackageJsonDependencies({ dependencies: { a: '^1.2.3' } }, { dependencies: { a: '^1.3.0', b: '^2.0.0' } });
 * // { dependencies: { a: '^1.3.0', b: '^2.0.0' } }
 * addPackageJsonDependencies({ dependencies: { a: '^1.2.3' } }, { devDependencies: { a: '^1.3.0', b: '^2.0.0' } });
 * // null
 */
declare function addPackageJsonDependencies(
  current: PackageJsonDependencies,
  updates: PackageJsonDependencies
): {
  dependencies?: Record<string, string> | undefined;
  devDependencies?: Record<string, string> | undefined;
  peerDependencies?: Record<string, string> | undefined;
  optionalDependencies?: Record<string, string> | undefined;
} | null;
/**
 * Removes provided dependencies from package.json.
 * @param current Current package.json content
 * @param updates Specific dependencies to remove
 * @return Object with new content if changed and null otherwise
 * @example
 * removePackageJsonDependencies({}, { dependencies: ['a'] });
 * // null
 * removePackageJsonDependencies({ dependencies: { a: '^1.2.3' } }, { dependencies: ['a'] });
 * // { dependencies: {} }
 * removePackageJsonDependencies({ dependencies: { a: '^1.2.3' } }, { dependencies: ['b'] });
 * // null
 * removePackageJsonDependencies({ dependencies: { a: '^1.2.3' } }, { dependencies: ['a', 'b'] });
 */
declare function removePackageJsonDependencies(
  current: PackageJsonDependencies,
  updates: Partial<Record<DependencyTypeName, string[]>>
): {
  dependencies?: Record<string, string> | undefined;
  devDependencies?: Record<string, string> | undefined;
  peerDependencies?: Record<string, string> | undefined;
  optionalDependencies?: Record<string, string> | undefined;
} | null;
declare function sortPackageJson<T extends PackageJsonDependencies>(value: T): T;
type PackageJsonDependencies = Partial<Record<DependencyTypeName, Record<string, string>>>;
type DependencyTypeName =
  | 'dependencies'
  | 'devDependencies'
  | 'peerDependencies'
  | 'optionalDependencies';

interface TransformPrettierOptions {
  (path: string, options: Options): Partial<Options> | void;
}
/**
 * Tries to format a file with prettier and returns the formatted content or null if it fails.
 * @param path Path to the file
 * @param content Content of the file
 * @param transform Optional function to transform prettier options
 * @return Formatted content or null if it fails or the file is ignored
 * @example
 * tryFormatPrettier('package.json', JSON.stringify({ a: 1, b: 2 }, null, 2));
 * // {
 * //   "a": 1,
 * //   "b": 2
 * // }
 * tryFormatPrettier('src/index.ts', 'const a=11,b=22;');
 * // const a = 11;
 * // const b = 22;
 * tryFormatPrettier('ignored.ts', 'const a=11,b=22;');
 * // null
 */
declare function tryFormatPrettier(
  path: string,
  content: string,
  transform?: TransformPrettierOptions
): Promise<string | null>;

/**
 * Check if incoming version is greater than existing version (including non-semver versions).
 * @param incoming Incoming version
 * @param existing Existing version
 * @return True if incoming version is greater than existing version
 */
declare function isGreaterVersion(incoming: string, existing: string): boolean;
/**
 * Get dependencies that have been upgraded compared to current dependencies.
 * @param changes Object with dependencies to upgrade
 * @param current Object with current dependencies
 * @return Object with dependencies that have been upgraded or null if nothing has been upgraded
 * @example
 * getUpgradedDependenciesVersions(
 *  { dependencies: { a: '^1.2.3', b: '^2.0.0' } },
 *  { dependencies: { a: '^1.2.3', b: '^1.0.0' } } // b is outdated
 * );
 * // { dependencies: { b: '^2.0.0' } }
 * getUpgradedDependenciesVersions(
 * { dependencies: { a: '^1.2.3', b: '^2.0.0' } },
 * { dependencies: { a: '^1.2.3', b: '^2.0.0' } } // nothing is outdated
 * );
 * // null
 */
declare function getUpgradedDependenciesVersions(
  changes: Record<string, string>,
  current: Record<string, string>
): {
  [k: string]: string;
} | null;

export {
  type DependencyTypeName,
  type PackageJsonDependencies,
  type TransformPrettierOptions,
  addPackageJsonDependencies,
  getUpgradedDependenciesVersions,
  isGreaterVersion,
  removePackageJsonDependencies,
  sortPackageJson,
  tryFormatPrettier
};
