import { describe, it, expect } from 'vitest';
import {
  computeEventSalience,
  defaultSinceTs,
  listDecayCandidates,
  rankMemoryResults,
} from '../salience';
import { DEFAULT_SALIENCE_THRESHOLDS } from '../team-hub-config';
import type { TeamMemoryEvent } from '../types';

function ev(id: string, ts: string): TeamMemoryEvent {
  return {
    eventId: id,
    teamId: 't1',
    agentId: 'a1',
    workspaceId: 'w1',
    eventType: 'task_created',
    timestamp: ts,
    payload: { taskId: id },
    summary: `event ${id}`,
    metadata: {},
  };
}

describe('salience', () => {
  it('defaultSinceTs uses interactionWindowDays', () => {
    const now = new Date('2026-05-20T12:00:00Z');
    const since = defaultSinceTs(DEFAULT_SALIENCE_THRESHOLDS, now);
    expect(since).toBe('2026-05-06T12:00:00.000Z');
  });

  it('older events have lower salience at same semantic score', () => {
    const now = new Date('2026-05-20T12:00:00Z');
    const recent = ev('r', '2026-05-19T12:00:00Z');
    const old = ev('o', '2026-01-01T12:00:00Z');
    const scores = new Map<string, number>([
      ['r', 1],
      ['o', 1],
    ]);
    const ranked = rankMemoryResults([old, recent], DEFAULT_SALIENCE_THRESHOLDS, scores, now);
    expect(ranked[0].eventId).toBe('r');
    expect(ranked[0].finalScore).toBeGreaterThan(ranked[1].finalScore);
  });

  it('access refresh increases salience vs stale same age', () => {
    const now = new Date('2026-05-20T12:00:00Z');
    const ts = '2026-05-01T12:00:00Z';
    const stale = computeEventSalience(ev('s', ts), DEFAULT_SALIENCE_THRESHOLDS, now);
    const refreshed = computeEventSalience(ev('s', ts), DEFAULT_SALIENCE_THRESHOLDS, now, {
      lastAccessedAt: '2026-05-19T12:00:00Z',
      accessCount: 3,
    });
    expect(refreshed).toBeGreaterThan(stale);
  });

  it('listDecayCandidates respects pinned', () => {
    const now = new Date('2026-05-20T12:00:00Z');
    const old = ev('old', '2025-01-01T12:00:00Z');
    old.metadata.pinned = true;
    const candidates = listDecayCandidates([old], DEFAULT_SALIENCE_THRESHOLDS, now);
    expect(candidates).toHaveLength(0);
  });
});
