import { recordSlowPrismaQuery, recordSlowRequest, clearOpsRuntimeEventsForTests } from './ops-runtime.store';
import { OpsService } from './ops.service';

describe('OpsService', () => {
  afterEach(() => clearOpsRuntimeEventsForTests());

  it('returns runtime performance counters without exposing secrets', async () => {
    const prisma = {
      backgroundJob: {
        findMany: jest.fn().mockResolvedValue([
          {
            id: 'job-queued',
            type: 'xiaobao.summary.refresh',
            status: 'queued',
            attempts: 0,
            maxAttempts: 5,
            availableAt: new Date('2026-07-08T08:00:00.000Z'),
            lockedUntil: null,
            lastError: null,
            updatedAt: new Date('2026-07-08T08:00:00.000Z'),
          },
          {
            id: 'job-running',
            type: 'xiaobao.ai.interpret',
            status: 'running',
            attempts: 1,
            maxAttempts: 3,
            availableAt: new Date('2026-07-08T08:01:00.000Z'),
            lockedUntil: new Date('2026-07-08T08:05:00.000Z'),
            lastError: null,
            updatedAt: new Date('2026-07-08T08:02:00.000Z'),
          },
          {
            id: 'job-failed',
            type: 'xiaobao.ai.interpret',
            status: 'failed',
            attempts: 3,
            maxAttempts: 3,
            availableAt: new Date('2026-07-08T08:03:00.000Z'),
            lockedUntil: null,
            lastError: 'provider failed with sk-secret-token',
            updatedAt: new Date('2026-07-08T08:04:00.000Z'),
          },
        ]),
      },
      xiaobaoRiskSummary: {
        count: jest.fn().mockResolvedValue(7),
      },
    };
    recordSlowRequest({
      method: 'POST',
      url: '/api/v1/ai/risk-interpret?token=sk-secret-token',
      durationMs: 1500,
      thresholdMs: 1000,
      occurredAt: new Date('2026-07-08T08:05:00.000Z'),
    });
    recordSlowPrismaQuery({
      query: 'SELECT * FROM background_jobs WHERE last_error = "sk-secret-token"',
      durationMs: 420,
      thresholdMs: 300,
      occurredAt: new Date('2026-07-08T08:06:00.000Z'),
    });
    const service = new OpsService(prisma as any);

    const snapshot = await service.getRuntimeSnapshot(new Date('2026-07-08T08:07:00.000Z'));

    expect(snapshot.dirtySummaryCount).toBe(7);
    expect(snapshot.jobQueue.totals).toEqual({ queued: 1, running: 1, succeeded: 0, failed: 1, total: 3 });
    expect(snapshot.jobQueue.byType).toEqual([
      expect.objectContaining({ type: 'xiaobao.ai.interpret', running: 1, failed: 1, total: 2 }),
      expect.objectContaining({ type: 'xiaobao.summary.refresh', queued: 1, total: 1 }),
    ]);
    expect(snapshot.jobQueue.recentFailures).toEqual([
      expect.objectContaining({
        id: 'job-failed',
        type: 'xiaobao.ai.interpret',
        lastError: expect.stringContaining('[redacted]'),
      }),
    ]);
    expect(snapshot.slowRequests[0].path).toBe('/api/v1/ai/risk-interpret');
    expect(snapshot.slowQueries[0].queryPreview).toContain('[redacted]');
    expect(JSON.stringify(snapshot)).not.toContain('sk-secret-token');
    expect(snapshot.access).toEqual({
      requiredPermission: 'ops:view',
      backendEnforced: false,
      adapter: 'OpsPermissionAdapter',
    });
  });
});
