import { MemoryCategory, MemoryFile } from './types.js';

/**
 * `remnic patterns` CLI helpers (issue #687 PR 4/4).
 *
 * Pure functions that:
 *
 *   1. Validate `--limit`, `--category`, `--since`, `--format` for
 *      `remnic patterns list` and `--format` for
 *      `remnic patterns explain <id>` (CLAUDE.md rules 14 + 51 — flags
 *      throw listed-options errors instead of silently defaulting).
 *
 *   2. Filter the memory corpus to canonical memories produced by the
 *      pattern-reinforcement maintenance job from issue #687 PR 2/4
 *      (`reinforcement_count > 0`) and sort them by reinforcement
 *      count, with `last_reinforced_at` (then `id`) as stable
 *      tiebreakers (CLAUDE.md rule 19).
 *
 *   3. Reconstruct a single canonical's full picture: its
 *      `derived_from` provenance chain (PR 2/4 stamps these), the
 *      cluster members it absorbed (memories pointing at it via
 *      `supersededBy`), and the canonical body so operators can read
 *      it inline.
 *
 *   4. Render `text` (default) / `markdown` / `json` output for both
 *      commands.  The CLI handler in `cli.ts` stays thin and delegates
 *      formatting here so HTTP / MCP surfaces (if added later) can
 *      reuse the same renderers (CLAUDE.md rule 22 — never fork
 *      formatting).
 */

declare const PATTERNS_OUTPUT_FORMATS: readonly ["text", "markdown", "json"];
type PatternsOutputFormat = (typeof PATTERNS_OUTPUT_FORMATS)[number];
/**
 * Validate `--format <fmt>`.  Throws a listed-options error for any
 * value not in `PATTERNS_OUTPUT_FORMATS`.  Returns `"text"` when the
 * value is `undefined` (no flag supplied).
 */
declare function parsePatternsFormat(value: unknown): PatternsOutputFormat;
/**
 * Validate `--limit <N>`.  Must be a positive integer.  Returns
 * `undefined` when the flag is absent (the caller falls back to a
 * default).
 */
declare function parsePatternsLimit(value: unknown): number | undefined;
/**
 * Validate `--category <list>`.  Accepts a comma-separated list of
 * non-empty trimmed tokens.  Returns the deduplicated list, or
 * `undefined` when no flag was supplied.  CLAUDE.md rules 14 + 51:
 * `--category` with no value or with a value that resolves to zero
 * tokens is rejected.
 */
declare function parsePatternsCategory(value: unknown): string[] | undefined;
/**
 * Validate `--since <ISO>`.  Delegates to `parseStrictCliDate` which
 * enforces a strict ISO 8601 shape and rejects calendar overflows and
 * non-ISO formats (e.g. "12/25/2026", "Dec 25 2026") that bare
 * `Date.parse()` would silently accept.  Returns the canonical ISO
 * string (round-trip through `toISOString`) so downstream comparisons
 * use a consistent form.
 */
declare function parsePatternsSince(value: unknown): string | undefined;
interface ParsedPatternsListOptions {
    format: PatternsOutputFormat;
    limit?: number;
    categories?: string[];
    sinceIso?: string;
}
interface ParsedPatternsExplainOptions {
    format: PatternsOutputFormat;
}
/**
 * Validate the full option bag for `remnic patterns list`.  Extracted
 * from the CLI handler so validation can be unit-tested without
 * booting an orchestrator (CLAUDE.md rules 14 + 51).
 */
declare function parsePatternsListOptions(options: Record<string, unknown>): ParsedPatternsListOptions;
/**
 * Validate `remnic patterns explain` options + positional id.  Throws
 * when `<memoryId>` is missing or empty.
 */
declare function parsePatternsExplainOptions(rawId: unknown, options: Record<string, unknown>): {
    id: string;
} & ParsedPatternsExplainOptions;
interface PatternListRow {
    id: string;
    category: MemoryCategory;
    reinforcementCount: number;
    lastReinforcedAt?: string;
    status: string;
    /** First non-empty content line, trimmed to ~120 chars for the table. */
    preview: string;
    /** Full path on disk (relative to memoryDir) for operators who want to inspect the file. */
    path: string;
}
/**
 * Filter, sort, and slice the memory corpus down to the rows the
 * `remnic patterns list` command should print.
 *
 * Rules (each one is exercised by `tests/cli/patterns.test.ts`):
 *
 *   - Memories without `reinforcement_count` (or with a count <= 0) are
 *     dropped — these are not pattern canonicals.
 *   - When `categories` is supplied, only memories whose
 *     `frontmatter.category` is in the list survive.
 *   - When `sinceIso` is supplied, only memories whose
 *     `last_reinforced_at` is `>= sinceIso` survive.  Memories without
 *     `last_reinforced_at` are dropped under `--since` (PR 2/4 always
 *     stamps the timestamp alongside the count, so a missing timestamp
 *     means a malformed file the operator should not see in this view).
 *   - Sort by `reinforcement_count DESC`, then `last_reinforced_at
 *     DESC`, then `id ASC` for a stable, deterministic order
 *     (CLAUDE.md rule 19).
 *   - Apply `limit` (default 50).
 */
declare function collectPatternMemories(memories: readonly MemoryFile[], opts: ParsedPatternsListOptions): PatternListRow[];
interface PatternDerivedFromEntry {
    /** Raw `"<path>:<version>"` reference exactly as stored in `derived_from`. */
    ref: string;
    /** Source memory id, or the path component for older `path:version` references. */
    path: string;
    /** Page-version number component for older `path:version` references. */
    version: number | null;
    /** True when an older path-version reference had an invalid version component. */
    malformed?: boolean;
}
interface PatternClusterMember {
    id: string;
    status: string;
    supersededAt?: string;
    path: string;
    preview: string;
}
interface PatternExplainDetail {
    id: string;
    category: MemoryCategory;
    reinforcementCount: number;
    lastReinforcedAt?: string;
    status: string;
    derivedVia?: string;
    /** Full canonical body (frontmatter stripped). */
    canonicalContent: string;
    canonicalPath: string;
    /** Parsed `derived_from` chain — empty when PR 2/4 did not stamp it. */
    derivedFrom: PatternDerivedFromEntry[];
    /** Memories whose `supersededBy === <id>`, sorted by `supersededAt DESC` then `id ASC`. */
    clusterMembers: PatternClusterMember[];
}
/**
 * Build the structured detail object for a single canonical.  Returns
 * `null` when the memory is not found or has never been touched by
 * pattern reinforcement (i.e., no `reinforcement_count`).  The CLI
 * handler then prints a clean "not a pattern" error rather than
 * leaking an empty document.
 */
declare function explainPatternMemory(memories: readonly MemoryFile[], id: string): PatternExplainDetail | null;
declare function renderPatternsList(rows: readonly PatternListRow[], format: PatternsOutputFormat): string;
declare function renderPatternExplain(detail: PatternExplainDetail, format: PatternsOutputFormat): string;

export { PATTERNS_OUTPUT_FORMATS, type ParsedPatternsExplainOptions, type ParsedPatternsListOptions, type PatternClusterMember, type PatternDerivedFromEntry, type PatternExplainDetail, type PatternListRow, type PatternsOutputFormat, collectPatternMemories, explainPatternMemory, parsePatternsCategory, parsePatternsExplainOptions, parsePatternsFormat, parsePatternsLimit, parsePatternsListOptions, parsePatternsSince, renderPatternExplain, renderPatternsList };
