import { ILogBasic, ILogLayer } from "lognow";
import { z } from "zod";
import { Root } from "mdast";
import { VFile } from "vfile";
import { JsonValue, MergeDeep, Simplify } from "type-fest";
import { Plugin } from "unified";

//#region src/lib/mdat/rules.d.ts
/**
 * Recursively simplifies a type for cleaner IDE hover display. Approximation of
 * type-fest's internal `SimplifyDeep`.
 */
type SimplifyDeep<T> = Simplify<MergeDeep<T, T>>;
/**
 * Context passed to rule content functions during expansion.
 */
type RuleContext = {
  /** File path of the source document, if known. */filePath: string | undefined; /** Parsed YAML frontmatter from the document, if present. */
  frontmatter: Record<string, unknown> | undefined; /** The full mdast AST of the document. Do not mutate. */
  tree: Root;
};
/**
 * Strict normalized rules used internally. Rules normalized to a form with
 * async content functions and other default metadata Simplifies processing
 * elsewhere, while retaining flexibility for rule authors
 */
type NormalizedRule = {
  /**
   * The function that generates the expanded Markdown string. For 'compound'
   * rules, this can be an array of rules (without keywords).
   */
  content: ((options: JsonValue, context: RuleContext) => Promise<string>) | NormalizedRule[];
  /**
   * The order in which the rule should be applied during processing Helpful if
   * a rule depends on the presence of content generated by another rule
   * Defaults to 0.
   */
  order: number;
};
type Rule =
/**
 * Function that returns the Markdown string to expand at the comment site.
 */
((options: JsonValue, context: RuleContext) => Promise<string> | string)
/**
 * Compound rules may be defined an array of rules, without keywords. Can be
 * defined at the top level, if no validation metadata is required, or as the
 * 'content' value of a rule object with validation metadata.
 */
| Rule[]
/**
 * The Markdown string to expand at the comment site.
 */
| string
/**
 * Rule object with optional metadata.
 */
| {
  /**
   * Gets content to expand into the comment. Can be a simple string for
   * direct replacement, a function that returns a string, or an async
   * function that returns a string.
   *
   * If a function is provided, it will be passed the following arguments:
   *
   * @param options JSON value of options parsed immediately after the
   *   comment keyword in the comment, e.g.: `<!-- keyword({something:
   *   true}) -->` or `<!-- keyword {something: true}-->` Sets options to
   *   {something: true}
   * @param context Rule context containing the mdast AST, parsed
   *   frontmatter, and file path.
   *
   * @returns A string with the generated content. The string will be parsed
   *   as Markdown and inserted into the document at the comment's
   *   location.
   */
  content: ((options: JsonValue, context: RuleContext) => Promise<string> | string) | Rule[] | string;
  /**
   * The order in which the rule should be applied during processing.
   * Defaults to 0.
   */
  order?: number;
};
/**
 * Rules are record objects whose keys match strings inside a Markdown comment,
 * and values explain what should be expanded at the comment site.
 *
 * The record value may be a string, or an object containing additional
 * metadata, possibly with a function to invoke to generate content.
 *
 * @example
 * 	Most basic rule:
 * 	```ts
 * 	{ basic: 'content' }
 * 	```
 *
 * 	Rule with dynamic content:
 * 	```ts
 * 	{ basic: () => `${new Date().toISOString()}` }
 * 	```
 *
 * 	Rule with metadata:
 * 	```ts
 * 	{ basic-meta: { order: 1, content: 'content'} }
 * 	```
 *
 * 	Rule with dynamic content and metadata:
 * 	{ basic-date: { order: 1, content: () => `${new Date().toISOString()}` } }
 */
type Rules = SimplifyDeep<Record<string, Rule>>;
/** A record mapping comment keywords to {@link NormalizedRule} objects. */
type NormalizedRules = SimplifyDeep<Record<string, NormalizedRule>>;
/** Zod schema for validating {@link Rules} records. */
declare const rulesSchema: z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
/**
 * Returns the rule value from a single-rule record. Useful when aliasing rules
 * or invoking them programmatically.
 *
 * Throws if there are no entries or more than one entry.
 */
declare function getSoleRule<T extends NormalizedRules | Rules>(rules: T): T[keyof T];
/**
 * Returns the rule key from a single-rule record. Useful for comment
 * placeholder validation.
 *
 * Throws if there are no entries or more than one entry.
 */
declare function getSoleRuleKey<T extends NormalizedRules | Rules>(rules: T): keyof T;
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat.d.ts
/**
 * Mdast utility that splits, collapses, and then re-expands all mdat comments
 * in the tree.
 */
declare function mdat(tree: Root, file: VFile, rules: NormalizedRules | Rules): Promise<void>;
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat-collapse.d.ts
/**
 * Collapses any expanded mdat comments, effectively resetting the document to
 * its pre-expansion state, preserving the original comments. No-op if no mdat
 * comments are found.
 */
declare function mdatCollapse(tree: Root, file: VFile): void;
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat-clean.d.ts
/**
 * @deprecated Use {@link mdatCollapse} instead. This alias will be removed in a
 *   future major version.
 */
declare const mdatClean: typeof mdatCollapse;
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat-diff.d.ts
/** Per-tag comparison result from {@link mdatDiff}. */
type MdatDiffResult = {
  /** The keyword for this tag. */keyword: string; /** 1-based line number of the opening comment in the expanded document. */
  line: number; /** Comparison status. */
  status: 'added' | 'missing' | 'ok' | 'stale' | 'unexpanded';
};
/**
 * Compare original and expanded documents per-tag. Walks both ASTs to extract
 * content between open/close comment markers, then compares per-tag.
 *
 * Callers should run {@link mdatSplit} on both trees before calling this
 * function to ensure multi-comment nodes are split into individual nodes.
 *
 * Adds diagnostic messages to `expandedFile` via the VFile message pipeline.
 *
 * @returns Per-tag comparison results.
 */
declare function mdatDiff(originalTree: Root, originalFile: VFile, expandedTree: Root, expandedFile: VFile): MdatDiffResult[];
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat-expand.d.ts
/**
 * Mdast utility to expand mdat comments in the tree.
 */
declare function mdatExpand(tree: Root, file: VFile, rules: NormalizedRules | Rules): Promise<void>;
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat-split.d.ts
/**
 * Mdast utility plugin to split any multi-comment nodes and their content into
 * individual MDAST HTML nodes. They're wrapped in a paragraph so as not to
 * introduce new breaks.
 */
declare function mdatSplit(tree: Root, file: VFile): void;
//#endregion
//#region src/lib/mdast-utils/mdast-util-mdat-strip.d.ts
/**
 * Strips all mdat comment nodes (both opening and closing) from the tree,
 * preserving any content between them. Code-style comments (`//`, `#`, `/*`)
 * are left untouched.
 */
declare function mdatStrip(tree: Root, _file: VFile): void;
//#endregion
//#region src/lib/mdat/log.d.ts
/**
 * Set the logger instance for the module. Export this for library consumers to
 * inject their own logger.
 *
 * @param logger - Accepts either a LogLayer instance or a Console- or
 *   Stream-like log target
 */
declare function setLogger(logger?: ILogBasic | ILogLayer<unknown>): void;
//#endregion
//#region src/lib/mdat/mdat-log.d.ts
/** A simplified representation of a {@link VFileMessage}. */
type MdatMessage = {
  /** Starting column of the message origin. */column?: number; /** Severity level. */
  level: 'error' | 'info' | 'warn'; /** Starting line of the message origin. */
  line?: number; /** Human-readable description of the issue. */
  message: string; /** Namespace that produced the message (e.g. the rule name). */
  source?: string;
};
/** Aggregated processing report for a single file. */
type MdatFileReport = {
  /** Output path if the file was written to a different location. */destinationPath?: string; /** Fatal errors that prevented successful processing. */
  errors: MdatMessage[]; /** Informational messages. */
  infos: MdatMessage[]; /** Original input file path. */
  sourcePath: string; /** Non-fatal warnings encountered during processing. */
  warnings: MdatMessage[];
};
/** Converts an array of processed VFiles into {@link MdatFileReport} objects. */
declare function getMdatReports(files: VFile[]): MdatFileReport[];
/** Logs a human-readable processing report for each VFile to the library logger. */
declare function reporterMdat(files: VFile[]): void;
//#endregion
//#region src/lib/remark-mdat.d.ts
/** Configuration for the remarkMdat plugin. */
type Options = {
  /**
   * Rules mapping comment keywords to expansion content. Merged with built-in
   * defaults.
   */
  rules?: Rules;
};
/** Zod schema for validating {@link Options}. */
declare const optionsSchema: z.ZodObject<{
  rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
}, z.core.$strip>;
/**
 * A remark plugin that expands HTML comments in Markdown files.
 */
declare const remarkMdat: Plugin<[Options?], Root>;
//#endregion
export { type MdatDiffResult, type MdatFileReport, type MdatMessage, type NormalizedRule, type NormalizedRules, type Options, type Rule, type RuleContext, type Rules, type SimplifyDeep, remarkMdat as default, getMdatReports, getSoleRule, getSoleRuleKey, mdat, mdatClean, mdatCollapse, mdatDiff, mdatExpand, mdatSplit, mdatStrip, optionsSchema, reporterMdat, rulesSchema, setLogger };