/** Minimum month-labelled cells on the row below the leaf header to treat it as a month sub-header row. */
export declare const MIN_MONTH_HEADER_CELLS = 6;
export type SheetMerge = {
    s: {
        r: number;
        c: number;
    };
    e: {
        r: number;
        c: number;
    };
};
export type YearAnchor = {
    col: number;
    year: number;
};
export type PenaltyColumnDescriptor = {
    col: number;
    calendarYear: number;
    calendarMonth: number;
    monthKey: string;
    compositeKey: string;
};
export type ImportPenaltyEntry = {
    calendarYear: number;
    calendarMonth: number;
    penaltyAmount: number;
};
export type HeaderHierarchy = {
    groupRowIdx: number | null;
    leafRowIdx: number;
    monthRowIdx: number | null;
    dataStartRowIdx: number;
    penaltyGroupCol: number | null;
    hasPenaltyGrid: boolean;
};
export type SchemeImportColumnModel = {
    hierarchy: HeaderHierarchy;
    penaltyStartCol: number;
    baseEndCol: number;
    width: number;
    yearAnchors: YearAnchor[];
    penaltyColumns: PenaltyColumnDescriptor[];
    baseKeys: string[];
};
export type SchemeImportLayoutWarning = {
    /** 1-based Excel row number. */
    excelRow: number;
    reason: string;
};
export type SchemeImportSheetParseResult = {
    records: Record<string, unknown>[];
    penaltiesByDataRowIndex: Map<number, ImportPenaltyEntry[]>;
    /** Per data-row index — non-empty when a penalty cell has 0, negative, or invalid numeric text. */
    penaltyErrorsByDataRowIndex: Map<number, string[]>;
    model: SchemeImportColumnModel;
    layoutWarnings: SchemeImportLayoutWarning[];
};
/** Normalize month label; returns canonical key or empty if unknown. */
export declare function normalizeMonthLabel(raw: string): string;
export declare function monthLabelToNumber(monthKey: string): number | null;
/** Content-driven header stack detection (no fixed row numbers). */
export declare function detectHeaderHierarchy(aoa: unknown[][]): HeaderHierarchy;
export declare function resolvePenaltyStartCol(aoa: unknown[][], hierarchy: HeaderHierarchy): number;
/** Discover `/^\d{4}$/` anchors on the leaf row from `penaltyStartCol` onward. */
export declare function discoverYearAnchors(leafRow: unknown[], penaltyStartCol: number): YearAnchor[];
/** Last anchor with `col <= c`. */
export declare function yearForColumn(c: number, anchors: YearAnchor[]): number | null;
export declare function discoverPenaltyColumns(leafRow: unknown[], monthRow: unknown[], penaltyStartCol: number, anchors: YearAnchor[]): {
    columns: PenaltyColumnDescriptor[];
    warnings: string[];
};
export declare function buildSchemeImportColumnModel(aoa: unknown[][], _merges?: SheetMerge[]): {
    model: SchemeImportColumnModel;
    warnings: string[];
};
export type PenaltyCellParseResult = {
    kind: 'skip';
} | {
    kind: 'amount';
    amount: number;
} | {
    kind: 'invalid';
    reason: string;
};
/** Parse one penalty grid cell (value must already be trimmed for display in errors). */
export declare function parsePenaltyCellAmount(raw: string): PenaltyCellParseResult;
/** Validate penalty cells after trim; empty / hyphen placeholders mean no penalty. */
export declare function validatePenaltyCellsInDataRow(dataRow: unknown[], model: SchemeImportColumnModel): string[];
export declare function extractPenaltiesFromDataRow(dataRow: unknown[], model: SchemeImportColumnModel): ImportPenaltyEntry[];
/** Parse full sheet AOA into base records + per-row penalty entries. */
export declare function parseSchemeImportSheet(aoa: unknown[][], merges?: SheetMerge[]): SchemeImportSheetParseResult;
/**
 * True if row key is a penalty grid column (year + month), not a worker role.
 * Matches raw composite keys (`2024__january`) and normalized keys (`2024_january`)
 * after {@link headerKeyToSnakeCase} collapses `__` → `_`.
 */
export declare function isSchemeImportPenaltyCompositeKey(key: string): boolean;
//# sourceMappingURL=schemeImport.penaltyGrid.d.ts.map