/**
 * Graph-ingest path for ICS calendar archives.
 *
 *   .ics file ──▶ parseICS ──▶ (dry-run preview │ commit writes)
 *
 * Writes one `:Meeting` per VEVENT, anchors it to the importing `:AdminUser`
 * via `[:IMPORTED]`, resolves attendees to `:Person` by lowercased email, and
 * MERGEs `[:ATTENDED]` edges with role + partstat.
 *
 * Cross-account collision rule: `Person.email` is globally unique in the
 * schema. When an attendee email already exists under a different accountId,
 * the import skips the attendance edge (no edge written, the foreign Person
 * is untouched) and increments `skippedCrossAccountPerson`. The Meeting still
 * lands, anchored to the importer's AdminUser. This preserves absolute brand
 * / account isolation while keeping the import as a whole non-fatal.
 */
import { Session } from "neo4j-driver";
import { type ParsedAttendee } from "./ics.js";
export interface IcsIngestParams {
    /** The .ics file content (already read by the tool wrapper). */
    fileContent: string;
    /** Path-cleansed filename used for diagnostics + `:Meeting.sourceFilename`. */
    filename: string;
    mode: "dry-run" | "commit";
    accountId: string;
    /** The importing AdminUser. Required — we anchor every Meeting to them. */
    userId: string;
    sessionId?: string;
    session: Session;
}
export interface AttendeePreviewEntry {
    address: string;
    displayName?: string;
    status: "existing-same-account" | "existing-cross-account" | "will-create" | "non-mailto";
    /** Set when status is existing-*. */
    existingDisplayName?: string;
}
export interface IcsIngestDryRunResult {
    mode: "dry-run";
    filename: string;
    importId: string;
    events: number;
    validMeetings: number;
    skippedNoUid: number;
    skippedNoStartTime: number;
    /** Aggregate attendee preview. */
    preview: {
        attendees: number;
        organizers: number;
        nonMailtoAttendees: number;
        existingSameAccount: number;
        existingCrossAccount: number;
        willCreate: number;
    };
    /** Up to 20 representative attendees, classified — surfaces what a commit would do. */
    sampleAttendees: AttendeePreviewEntry[];
    parseErrors: string[];
    ms: number;
}
export interface IcsIngestCommitResult {
    mode: "commit";
    filename: string;
    importId: string;
    events: number;
    meetingsCreated: number;
    meetingsUpdated: number;
    peopleCreated: number;
    existingPersonsLinked: number;
    attendees: number;
    organizers: number;
    skippedNoUid: number;
    skippedNoStartTime: number;
    skippedCrossAccountPerson: number;
    parseErrors: string[];
    ms: number;
}
export type IcsIngestResult = IcsIngestDryRunResult | IcsIngestCommitResult;
export declare function ingestIcs(params: IcsIngestParams): Promise<IcsIngestResult>;
export type { ParsedAttendee };
//# sourceMappingURL=ics-graph-ingest.d.ts.map