import { WeixinArchiveSyncService } from '../../../../src/modules/netaclaw/service/weixin_archive_sync.js';

function mkLogger() {
  return { info: jest.fn(), warn: jest.fn(), error: jest.fn(), debug: jest.fn() };
}

describe('WeixinArchiveSyncService concurrency', () => {
  it('serializes calls within the same channel', async () => {
    const svc = new WeixinArchiveSyncService();
    (svc as any).logger = mkLogger();

    const startTimes: Record<number, number> = {};
    const endTimes: Record<number, number> = {};

    let counter = 0;
    (svc as any).doSyncGroup = async (group: any) => {
      const id = ++counter;
      startTimes[id] = Date.now();
      await new Promise(r => setTimeout(r, 50));
      endTimes[id] = Date.now();
      return { newCount: 0, totalCount: 0, lastSyncTs: 0, durationMs: 50 };
    };
    (svc as any).groupRepo = {
      findOne: jest.fn().mockImplementation(async ({ where: { id } }: any) => ({ id, channelId: 1 })),
    };

    await Promise.all([svc.syncGroup(11), svc.syncGroup(12), svc.syncGroup(13)]);
    expect(startTimes[2]).toBeGreaterThanOrEqual(endTimes[1]);
    expect(startTimes[3]).toBeGreaterThanOrEqual(endTimes[2]);
  });

  it('runs in parallel across different channels', async () => {
    const svc = new WeixinArchiveSyncService();
    (svc as any).logger = mkLogger();

    const startTimes: Record<number, number> = {};
    (svc as any).doSyncGroup = async (group: any) => {
      startTimes[group.id] = Date.now();
      await new Promise(r => setTimeout(r, 50));
      return { newCount: 0, totalCount: 0, lastSyncTs: 0, durationMs: 50 };
    };
    (svc as any).groupRepo = {
      findOne: jest.fn()
        .mockResolvedValueOnce({ id: 21, channelId: 1 })
        .mockResolvedValueOnce({ id: 22, channelId: 2 }),
    };
    await Promise.all([svc.syncGroup(21), svc.syncGroup(22)]);
    expect(Math.abs(startTimes[21] - startTimes[22])).toBeLessThan(20);
  });
});
