// packages/backend/src/modules/netaclaw/memory/registry.ts
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { NetaClawAgentEntity } from '../entity/agent.js';
import { NetaClawMemoryEntity } from '../entity/memory.js';
import { MemoryProvider, AgentMemoryConfig } from './provider.js';
import { createMemoryProvider } from './factory.js';

interface CachedProvider {
  provider: MemoryProvider;
  backend: string;
}

@Provide()
@Scope(ScopeEnum.Singleton)
export class MemoryProviderRegistry {
  private cache = new Map<string, CachedProvider>();

  @InjectEntityModel(NetaClawAgentEntity)
  agentEntity: Repository<NetaClawAgentEntity>;

  @InjectEntityModel(NetaClawMemoryEntity)
  memoryEntity: Repository<NetaClawMemoryEntity>;

  async getProvider(agentName: string): Promise<CachedProvider> {
    const cached = this.cache.get(agentName);
    if (cached) return cached;

    const agent = await this.agentEntity.findOneBy({ name: agentName });
    const memoryConfig: AgentMemoryConfig = agent?.config?.memory ?? { enabled: true, backend: 'mysql' };
    const provider = createMemoryProvider(memoryConfig, this.memoryEntity);
    const entry: CachedProvider = { provider, backend: memoryConfig.backend };
    this.cache.set(agentName, entry);
    return entry;
  }

  invalidate(agentName: string): void {
    const cached = this.cache.get(agentName);
    if (cached) {
      cached.provider.close?.();
      this.cache.delete(agentName);
    }
  }

  async getAllAgentsWithMemory(): Promise<Array<{ name: string; backend: string }>> {
    const agents = await this.agentEntity.find();
    return agents
      .filter(a => a.config?.memory?.enabled !== false)
      .map(a => ({
        name: a.name,
        backend: a.config?.memory?.backend ?? 'mysql',
      }));
  }
}
