/**
 * Typed reference parsing for wikilink-style fields.
 *
 * A reference value (e.g. `task.assignee`) can name one of two things:
 *
 *   - an ENTITY in the graph:  `[[jane-doe]]`, `[[repo/jane-doe|Jane]]`
 *   - a user ACCOUNT:          `[[user:42|@chris]]`
 *
 * The account form keys on the IMMUTABLE account id (`42`); the trailing
 * `@chris` is a human/grep display cache only and is NEVER identity — a renamed
 * handle leaves the stored label stale but the id keeps resolving. This keeps
 * "who is assigned" stable across handle renames / recycling, which a
 * handle-keyed ref could not.
 *
 * This module is dependency-free so it can be shared by the server, the core
 * graph layer, and the web client (`@core/refs`). It is the single source of
 * truth for ref parsing — ad-hoc `[[...]]` regexes elsewhere should defer here.
 */
const WIKILINK = /^\[\[(.+)\]\]$/;
const USER_PREFIX = 'user:';
/**
 * Parse a raw reference value into a {@link ParsedRef}. Accepts the bracketed
 * wikilink forms and a bare inner token. Returns null when there's nothing to
 * resolve (empty / non-string / malformed).
 */
export function parseRef(raw) {
    if (typeof raw !== 'string')
        return null;
    let s = raw.trim();
    if (!s)
        return null;
    const m = s.match(WIKILINK);
    if (m)
        s = m[1].trim();
    // Split the display label (everything after the first pipe).
    let label;
    const pipe = s.indexOf('|');
    if (pipe >= 0) {
        label = s.slice(pipe + 1).trim() || undefined;
        s = s.slice(0, pipe).trim();
    }
    if (!s)
        return null;
    // Account reference: user:<id>
    if (s.startsWith(USER_PREFIX)) {
        const userId = s.slice(USER_PREFIX.length).trim();
        if (!userId)
            return null;
        const handle = (label ?? '').replace(/^@/, '').trim() || undefined;
        return { kind: 'user', userId, handle, label };
    }
    // Entity reference, optionally repo-qualified (repo/id).
    let repo;
    if (s.includes('/')) {
        const parts = s.split('/');
        s = (parts.pop() ?? '').trim();
        const head = parts.join('/').trim();
        if (head)
            repo = head;
    }
    if (!s)
        return null;
    return { kind: 'entity', id: s, repo, label };
}
/** True when the raw value is an account/user reference (`[[user:…]]`). */
export function isUserRef(raw) {
    return parseRef(raw)?.kind === 'user';
}
/** Format a canonical account reference. The handle is a display cache only. */
export function formatUserRef(userId, handle) {
    const id = String(userId).trim();
    const h = (handle ?? '').replace(/^@/, '').trim();
    return h ? `[[user:${id}|@${h}]]` : `[[user:${id}]]`;
}
/** Format a canonical entity reference. */
export function formatEntityRef(id, label) {
    const l = (label ?? '').trim();
    return l ? `[[${id}|${l}]]` : `[[${id}]]`;
}
//# sourceMappingURL=refs.js.map