

export class RuntimeObjectIndex {
  private readonly index = new Map<string, any>();
  private readonly ensureObjectId: (obj: any) => string | null | undefined;
  private readonly listRuntimeObjects: () => any[];

  constructor(params: {
    ensureObjectId: (obj: any) => string | null | undefined;
    listRuntimeObjects: () => any[];
  }) {
    this.ensureObjectId = params.ensureObjectId;
    this.listRuntimeObjects = params.listRuntimeObjects;
  }

  track(obj: any): void {
    if (!obj) return;
    const objectId = String((obj as any)?._asukaObjectId ?? this.ensureObjectId(obj) ?? '').trim();
    if (!objectId) return;
    this.index.set(objectId, obj);
  }

  untrack(obj: any): void {
    if (!obj) return;
    const objectId = String((obj as any)?._asukaObjectId ?? '').trim();
    if (!objectId) return;
    const current = this.index.get(objectId);
    if (!current || current === obj) this.index.delete(objectId);
  }

  clear(): void {
    this.index.clear();
  }

  rebuild(): void {
    this.index.clear();
    const objects = this.listRuntimeObjects();
    for (const obj of Array.isArray(objects) ? objects : []) this.track(obj);
  }

  get(objectId: string | null | undefined): any | null {
    const id = String(objectId ?? '').trim();
    if (!id) return null;
    const direct = this.index.get(id);
    if (direct) return direct;
    this.rebuild();
    return this.index.get(id) ?? null;
  }

  getMany(ids: string[] | null | undefined): any[] {
    return (Array.isArray(ids) ? ids : []).map((id) => this.get(id)).filter(Boolean);
  }

  values(): any[] {
    return Array.from(this.index.values());
  }
}
