/**
 * 进程注册表服务
 *
 * 集中管理 Agent 进程生命周期状态，支持进程注册、追踪、状态管理和持久化
 */
import os from 'node:os';
import path from 'node:path';
import { promises as fs } from 'node:fs';
import { createLogger } from '../utils/logger.js';
import { atomicWriteJsonFile, withFileLock } from '../utils/file-utils.js';
const log = createLogger('process-registry');
/**
 * 获取持久化注册表文件路径
 *
 * @returns 注册表文件路径
 */
export function getProcessRegistryFile() {
    return path.join(os.tmpdir(), 'agentswork-runtime-bridge', 'process-registry.json');
}
/**
 * 进程注册表类
 *
 * 管理所有 Agent 进程的生命周期状态，提供注册、查询、更新和持久化功能
 */
export class ProcessRegistry {
    /**
     * 私有构造函数，强制使用单例模式
     */
    constructor() {
        this.records = new Map();
        this.pidToAgentId = new Map();
    }
    /**
     * 获取 ProcessRegistry 单例实例
     *
     * @returns ProcessRegistry 实例
     */
    static getInstance() {
        if (ProcessRegistry.instance === null) {
            ProcessRegistry.instance = new ProcessRegistry();
        }
        return ProcessRegistry.instance;
    }
    /**
     * 持久化注册表状态到文件
     */
    async persist() {
        const filePath = getProcessRegistryFile();
        try {
            const records = Array.from(this.records.values());
            await atomicWriteJsonFile(filePath, records);
            log.debug(`[persist] 已持久化 ${records.length} 条进程记录`);
        }
        catch (error) {
            log.error('[persist] 持久化失败:', error);
        }
    }
    async mutate(operation) {
        return withFileLock(getProcessRegistryFile(), async () => operation());
    }
    /**
     * 注册新进程
     *
     * @param record - 进程记录（不包含 createdAt）
     * @returns 是否注册成功
     */
    async register(record) {
        await this.mutate(async () => {
            const fullRecord = {
                ...record,
                createdAt: new Date().toISOString(),
            };
            // 如果已存在相同 agentId，先移除旧的映射
            const existing = this.records.get(record.agentId);
            if (existing) {
                this.pidToAgentId.delete(existing.pid);
            }
            this.records.set(record.agentId, fullRecord);
            this.pidToAgentId.set(record.pid, record.agentId);
            log.info(`[register] 注册进程: agentId=${record.agentId}, pid=${record.pid}, mode=${record.mode}, state=${record.state}`);
            await this.persist();
        });
    }
    /**
     * 更新进程记录
     *
     * @param agentId - Agent ID
     * @param updates - 要更新的字段
     * @returns 是否更新成功
     */
    async update(agentId, updates) {
        return this.mutate(async () => {
            const record = this.records.get(agentId);
            if (!record) {
                log.warn(`[update] 未找到进程: agentId=${agentId}`);
                return false;
            }
            // 如果更新包含 pid，需要更新 pid 映射
            if (updates.pid !== undefined && updates.pid !== record.pid) {
                this.pidToAgentId.delete(record.pid);
                this.pidToAgentId.set(updates.pid, agentId);
            }
            Object.assign(record, updates);
            log.debug(`[update] 更新进程: agentId=${agentId}, updates=${JSON.stringify(updates)}`);
            await this.persist();
            return true;
        });
    }
    /**
     * 通过 agentId 获取进程记录
     *
     * @param agentId - Agent ID
     * @returns 进程记录或 undefined
     */
    get(agentId) {
        return this.records.get(agentId);
    }
    /**
     * 通过 PID 获取进程记录
     *
     * @param pid - 进程 ID
     * @returns 进程记录或 undefined
     */
    getByPid(pid) {
        const agentId = this.pidToAgentId.get(pid);
        if (!agentId) {
            return undefined;
        }
        return this.records.get(agentId);
    }
    /**
     * 获取所有进程记录
     *
     * @returns 所有进程记录的数组
     */
    getAll() {
        return Array.from(this.records.values());
    }
    /**
     * 通过状态过滤进程记录
     *
     * @param state - 进程状态
     * @returns 符合状态的进程记录数组
     */
    getByState(state) {
        return this.getAll().filter(record => record.state === state);
    }
    /**
     * 检查进程是否被管理
     *
     * @param agentId - Agent ID
     * @returns 是否被管理
     */
    isManaged(agentId) {
        return this.records.has(agentId);
    }
    /**
     * 检查 PID 是否被管理
     *
     * @param pid - 进程 ID
     * @returns 是否被管理
     */
    isManagedByPid(pid) {
        return this.pidToAgentId.has(pid);
    }
    /**
     * 标记进程为孤儿状态
     *
     * @param agentId - Agent ID
     * @returns 是否标记成功
     */
    async markOrphaned(agentId) {
        return this.mutate(async () => {
            const record = this.records.get(agentId);
            if (!record) {
                log.warn(`[markOrphaned] 未找到进程: agentId=${agentId}`);
                return false;
            }
            record.state = 'orphaned';
            record.orphanedAt = new Date().toISOString();
            log.info(`[markOrphaned] 标记进程为孤儿: agentId=${agentId}, orphanedAt=${record.orphanedAt}`);
            await this.persist();
            return true;
        });
    }
    /**
     * 标记进程为终止状态
     *
     * @param agentId - Agent ID
     * @returns 是否标记成功
     */
    async markTerminated(agentId) {
        return this.mutate(async () => {
            const record = this.records.get(agentId);
            if (!record) {
                log.warn(`[markTerminated] 未找到进程: agentId=${agentId}`);
                return false;
            }
            record.state = 'terminated';
            log.info(`[markTerminated] 标记进程为终止: agentId=${agentId}`);
            await this.persist();
            return true;
        });
    }
    /**
     * 移除进程记录
     *
     * @param agentId - Agent ID
     * @returns 是否移除成功
     */
    async remove(agentId) {
        return this.mutate(async () => {
            const record = this.records.get(agentId);
            if (!record) {
                log.warn(`[remove] 未找到进程: agentId=${agentId}`);
                return false;
            }
            this.records.delete(agentId);
            this.pidToAgentId.delete(record.pid);
            log.info(`[remove] 移除进程: agentId=${agentId}, pid=${record.pid}`);
            await this.persist();
            return true;
        });
    }
    /**
     * 更新进程心跳时间
     *
     * @param agentId - Agent ID
     * @returns 是否更新成功
     */
    async updateHeartbeat(agentId) {
        return this.mutate(async () => {
            const record = this.records.get(agentId);
            if (!record) {
                log.warn(`[updateHeartbeat] 未找到进程: agentId=${agentId}`);
                return false;
            }
            record.lastHeartbeat = new Date().toISOString();
            log.debug(`[updateHeartbeat] 更新心跳: agentId=${agentId}, lastHeartbeat=${record.lastHeartbeat}`);
            await this.persist();
            return true;
        });
    }
    /**
     * 更新进程健康状态
     *
     * @param agentId - Agent ID
     * @param health - 健康状态
     * @returns 是否更新成功
     */
    async updateHealth(agentId, health) {
        return this.mutate(async () => {
            const record = this.records.get(agentId);
            if (!record) {
                log.warn(`[updateHealth] 未找到进程: agentId=${agentId}`);
                return false;
            }
            record.healthStatus = health;
            log.debug(`[updateHealth] 更新健康状态: agentId=${agentId}, health=${JSON.stringify(health)}`);
            await this.persist();
            return true;
        });
    }
    /**
     * 从持久化会话重建注册表
     *
     * @param sessions - 持久化会话数组
     */
    async rebuildFromPersisted(sessions) {
        await this.mutate(async () => {
            log.info(`[rebuildFromPersisted] 从 ${sessions.length} 个持久化会话重建注册表`);
            this.records.clear();
            this.pidToAgentId.clear();
            for (const session of sessions) {
                if (!session.pid) {
                    log.warn(`[rebuildFromPersisted] 跳过无 PID 的会话: agentId=${session.agentId}`);
                    continue;
                }
                const record = {
                    agentId: session.agentId,
                    sessionId: session.sessionId,
                    pid: session.pid,
                    mode: 'sdk',
                    state: 'unknown', // 重建时状态未知，需要外部检测
                    workspacePath: session.workspacePath || '',
                    command: session.command || '',
                    createdAt: new Date().toISOString(),
                };
                this.records.set(record.agentId, record);
                this.pidToAgentId.set(record.pid, record.agentId);
                log.debug(`[rebuildFromPersisted] 重建进程记录: agentId=${record.agentId}, pid=${record.pid}`);
            }
            log.info(`[rebuildFromPersisted] 重建完成，共 ${this.records.size} 条记录`);
            await this.persist();
        });
    }
    /**
     * 导出所有进程记录用于持久化
     *
     * @returns 所有进程记录的数组
     */
    exportState() {
        return this.getAll();
    }
    /**
     * 获取进程数量统计
     *
     * @returns 各状态的进程数量
     */
    getStats() {
        const stats = {
            creating: 0,
            running: 0,
            stopping: 0,
            orphaned: 0,
            terminated: 0,
            unknown: 0,
            total: this.records.size,
        };
        for (const record of this.records.values()) {
            stats[record.state]++;
        }
        return stats;
    }
    /**
     * 清空所有进程记录
     */
    async clear() {
        await this.mutate(async () => {
            const count = this.records.size;
            this.records.clear();
            this.pidToAgentId.clear();
            log.info(`[clear] 清空所有进程记录: ${count} 条`);
            await this.persist();
        });
    }
}
ProcessRegistry.instance = null;
/**
 * 获取 ProcessRegistry 单例实例的便捷函数
 *
 * @returns ProcessRegistry 实例
 */
export function getProcessRegistry() {
    return ProcessRegistry.getInstance();
}
/**
 * 加载持久化的进程注册表
 *
 * @returns 进程记录数组
 */
export async function loadPersistedProcessRegistry() {
    const filePath = getProcessRegistryFile();
    try {
        const raw = await fs.readFile(filePath, 'utf-8');
        const records = JSON.parse(raw);
        log.debug(`[loadPersistedProcessRegistry] 加载了 ${records.length} 条进程记录`);
        return records;
    }
    catch {
        return [];
    }
}
/**
 * 保存进程注册表到持久化文件
 *
 * @param records - 进程记录数组
 */
export async function savePersistedProcessRegistry(records) {
    const filePath = getProcessRegistryFile();
    await withFileLock(filePath, async () => {
        await atomicWriteJsonFile(filePath, records);
        log.debug(`[savePersistedProcessRegistry] 保存了 ${records.length} 条进程记录`);
    });
}
