import dayjs from 'dayjs';
export const SESSION_LEASE_REFRESH_INTERVAL_MS = 5 * 1000;
export const SESSION_LEASE_STALE_AFTER_MS = 20 * 1000;
const LOCAL_PROCESS_LEASE_OWNER_PATTERN = /^(?:tui|ask|submit|daemon)-(\d+)(?:-\d+)?$/;
export class ChatSessionLeases {
    static isFresh(lease, options) {
        if (!lease) {
            return false;
        }
        const lastSeenAt = dayjs(lease.lastSeenAt);
        if (!lastSeenAt.isValid()) {
            return false;
        }
        return dayjs(options?.now ?? Date.now()).diff(lastSeenAt) <= (options?.staleAfterMs ?? SESSION_LEASE_STALE_AFTER_MS);
    }
    static isOwnedByDeadLocalProcess(lease, options) {
        if (!lease) {
            return false;
        }
        const match = LOCAL_PROCESS_LEASE_OWNER_PATTERN.exec(lease.ownerId);
        const pid = match ? Number.parseInt(match[1] ?? '', 10) : NaN;
        if (!Number.isInteger(pid) || pid <= 0) {
            return false;
        }
        const isProcessAlive = options?.isProcessAlive ?? ChatSessionLeases.defaultIsProcessAlive;
        return !isProcessAlive(pid);
    }
    static acquire(session, owner, options) {
        const timestamp = dayjs(options?.now ?? Date.now()).toISOString();
        return {
            ...session,
            lease: {
                ownerKind: owner.ownerKind,
                ownerId: owner.ownerId,
                acquiredAt: session.lease?.ownerId === owner.ownerId ? session.lease.acquiredAt : timestamp,
                lastSeenAt: timestamp,
                clientLabel: owner.clientLabel,
            },
        };
    }
    static refresh(session, owner, options) {
        if (!session.lease || session.lease.ownerId !== owner.ownerId) {
            return session;
        }
        return {
            ...session,
            lease: {
                ...session.lease,
                lastSeenAt: dayjs(options?.now ?? Date.now()).toISOString(),
            },
        };
    }
    static release(session, owner) {
        if (!session.lease || (owner && session.lease.ownerId !== owner.ownerId)) {
            return session;
        }
        return {
            ...session,
            lease: undefined,
        };
    }
    static conflict(session, owner, options) {
        if (!session.lease ||
            session.lease.ownerId === owner.ownerId ||
            ChatSessionLeases.isOwnedByDeadLocalProcess(session.lease, options) ||
            !ChatSessionLeases.isFresh(session.lease, options)) {
            return undefined;
        }
        return [
            `Session ${session.id} is already active in ${session.lease.clientLabel ?? `${session.lease.ownerKind} (${session.lease.ownerId})`}.`,
            'Continuing from multiple clients in the same session may corrupt the conversation.',
            'Wait for the other client to finish or use a different session.',
        ].join(' ');
    }
    static defaultIsProcessAlive(pid) {
        try {
            process.kill(pid, 0);
            return true;
        }
        catch (error) {
            if (typeof error === 'object' && error && 'code' in error && error.code === 'ESRCH') {
                return false;
            }
            return true;
        }
    }
}
//# sourceMappingURL=leases.js.map