import { irohTransport } from './iroh-transport.js';
export class IrohDiscoveryService {
    config;
    discoveredAgents = new Map();
    ownIrohNodeId = null;
    refreshTimer = null;
    discoveryTimer = null;
    isRegistered = false;
    constructor(config) {
        this.config = {
            discoveryIntervalMs: 30000,
            refreshIntervalMs: 5 * 60 * 1000,
            ...config,
        };
    }
    async start() {
        console.log('[IrohDiscovery] Starting...');
        const node = await irohTransport.start();
        this.ownIrohNodeId = node.nodeId;
        console.log('[IrohDiscovery] Iroh node ID:', this.ownIrohNodeId.substring(0, 16) + '...');
        await this.registerWithDIAP();
        this.isRegistered = true;
        this.startRefreshLoop();
        this.startDiscoveryLoop();
        return this.ownIrohNodeId;
    }
    async registerWithDIAP() {
        if (!this.ownIrohNodeId)
            return;
        try {
            const services = [
                { serviceType: 'iroh', endpoint: this.ownIrohNodeId },
                { serviceType: 'iroh-quic', endpoint: `iroh://${this.ownIrohNodeId}` },
            ];
            const agentInfo = {
                name: this.config.agentName,
                services: services,
                description: this.config.agentDescription || 'Bolloon agent with iroh P2P',
                tags: this.config.agentTags || ['bolloon', 'iroh'],
            };
            await this.config.agentAuthManager.registerAgent(agentInfo, this.config.keyPair, this.ownIrohNodeId);
            console.log('[IrohDiscovery] Registered with DIAP');
        }
        catch (e) {
            console.warn('[IrohDiscovery] DIAP registration failed:', e);
        }
    }
    startRefreshLoop() {
        this.refreshTimer = setInterval(async () => {
            if (!this.isRegistered)
                return;
            console.log('[IrohDiscovery] Refreshing DIAP registration...');
            await this.registerWithDIAP();
        }, this.config.refreshIntervalMs);
    }
    startDiscoveryLoop() {
        const interval = this.config.discoveryIntervalMs ?? 30000;
        this.discoveryTimer = setInterval(async () => {
            await this.discoverPeers();
        }, interval);
        setTimeout(() => this.discoverPeers(), 2000);
    }
    async discoverPeers() {
        console.log('[IrohDiscovery] Discovering peers...');
        const now = Date.now();
        const staleThreshold = 10 * 60 * 1000;
        for (const [did, agent] of this.discoveredAgents) {
            if (now - agent.lastSeen > staleThreshold) {
                this.discoveredAgents.delete(did);
            }
        }
        console.log('[IrohDiscovery] Known agents:', this.discoveredAgents.size);
        return Array.from(this.discoveredAgents.values());
    }
    async discoverViaDIAP() {
        console.log('[IrohDiscovery] Querying DIAP for agents...');
        const agents = [];
        try {
            const ipfsClient = this.config.agentAuthManager.identityManager?.ipfsClient;
            if (ipfsClient) {
                console.log('[IrohDiscovery] IPFS client available for discovery');
            }
        }
        catch (e) {
            console.warn('[IrohDiscovery] DIAP discovery error:', e);
        }
        return agents;
    }
    addDiscoveredAgent(agent) {
        const existing = this.discoveredAgents.get(agent.did);
        this.discoveredAgents.set(agent.did, {
            ...agent,
            lastSeen: Date.now(),
            irohNodeId: agent.irohNodeId || existing?.irohNodeId || null,
        });
    }
    getDiscoveredAgents() {
        return Array.from(this.discoveredAgents.values());
    }
    getAgentByDid(did) {
        return this.discoveredAgents.get(did);
    }
    getAgentsWithIroh() {
        return Array.from(this.discoveredAgents.values()).filter((a) => a.irohNodeId !== null);
    }
    getOwnIrohNodeId() {
        return this.ownIrohNodeId;
    }
    async connectToPeer(nodeId) {
        return irohTransport.connect(nodeId);
    }
    async connectToAllIrohPeers() {
        const agents = this.getAgentsWithIroh();
        for (const agent of agents) {
            if (agent.irohNodeId && agent.irohNodeId !== this.ownIrohNodeId) {
                await this.connectToPeer(agent.irohNodeId);
            }
        }
    }
    async shutdown() {
        this.isRegistered = false;
        if (this.refreshTimer) {
            clearInterval(this.refreshTimer);
            this.refreshTimer = null;
        }
        if (this.discoveryTimer) {
            clearInterval(this.discoveryTimer);
            this.discoveryTimer = null;
        }
        this.discoveredAgents.clear();
        await irohTransport.shutdown();
        console.log('[IrohDiscovery] Shut down');
    }
}
let discoveryInstance = null;
export async function startIrohDiscovery(config) {
    if (discoveryInstance) {
        return discoveryInstance;
    }
    discoveryInstance = new IrohDiscoveryService(config);
    await discoveryInstance.start();
    return discoveryInstance;
}
export function getIrohDiscovery() {
    return discoveryInstance;
}
