import { describe, it, expect } from 'vitest';
import { generateMemo, isoWeekTag, sanitizeSlug } from '@/lib/claude-code/memo.js';

describe('claude-code/memo', () => {
  it('isoWeekTag formats as YYYY-Wxx', () => {
    const t = isoWeekTag(new Date('2026-05-12T12:00:00Z'));
    expect(/^\d{4}-W\d{2}$/.test(t)).toBe(true);
  });

  it('sanitizeSlug strips unsafe characters', () => {
    expect(sanitizeSlug('demo/project name!')).toBe('demo_project_name_');
  });

  it('generateMemo renders all required sections for a fixed window', () => {
    const project = { id: 1, slug: 'demo' };
    const sessions = [
      { session_uuid: 'a', cost_usd: 0.10, message_count: 3, started_at: '2026-05-08T01:00:00Z', model_primary: 'claude-opus-4-7', input_tokens: 100, output_tokens: 50, cache_read_tokens: 500, cache_creation_tokens: 50, cache_savings_usd: 0.01 },
      { session_uuid: 'b', cost_usd: 0.50, message_count: 6, started_at: '2026-05-09T01:00:00Z', model_primary: 'claude-opus-4-7', input_tokens: 200, output_tokens: 100, cache_read_tokens: 1000, cache_creation_tokens: 100, cache_savings_usd: 0.02 },
      { session_uuid: 'c', cost_usd: 2.00, message_count: 15, started_at: '2026-05-10T01:00:00Z', model_primary: 'claude-opus-4-7', input_tokens: 300, output_tokens: 200, cache_read_tokens: 1500, cache_creation_tokens: 150, cache_savings_usd: 0.04 },
      { session_uuid: 'd', cost_usd: 0.25, message_count: 4, started_at: '2026-05-10T02:00:00Z', model_primary: 'claude-opus-4-7', input_tokens: 80, output_tokens: 30, cache_read_tokens: 400, cache_creation_tokens: 40, cache_savings_usd: 0.005 },
      { session_uuid: 'e', cost_usd: 1.00, message_count: 8, started_at: '2026-05-11T03:00:00Z', model_primary: 'claude-opus-4-7', input_tokens: 250, output_tokens: 150, cache_read_tokens: 1200, cache_creation_tokens: 120, cache_savings_usd: 0.03 },
    ];
    const priorSessions = [
      { session_uuid: 'p1', cost_usd: 0.40, message_count: 5, model_primary: 'claude-opus-4-7', input_tokens: 100, output_tokens: 50, cache_read_tokens: 5000, cache_creation_tokens: 1000 },
    ];
    const memo = generateMemo({
      project,
      sessions,
      priorSessions,
      findings: [],
      stuckLoopTotal: 0,
      now: new Date('2026-05-12T00:00:00Z'),
    });
    expect(memo.markdown).toMatch(/Weekly Code Sessions memo — demo/);
    expect(memo.markdown).toMatch(/Total spend:/);
    expect(memo.markdown).toMatch(/Top 3 sessions by cost/);
    expect(memo.markdown).toMatch(/Repeated-run signals/);
    expect(memo.markdown).toMatch(/Optimizer findings/);
    expect(memo.markdown).toMatch(/What changed/);
    expect(memo.markdown).toMatch(/Generated by DashClaw/);
    // Top-3 ordering: $2.00 session 'c' must appear
    const topSection = memo.markdown.split('Top 3 sessions by cost')[1] || '';
    expect(topSection.includes('$2.00')).toBe(true);
    expect(memo.summary.sessions).toBe(5);
    expect(Math.abs(memo.summary.totalSpend - 3.85)).toBeLessThan(1e-6);
  });

  it('generateMemo flags a cache-hit drop in What changed', () => {
    const project = { id: 1, slug: 'demo' };
    const priorSessions = [
      { input_tokens: 100, cache_read_tokens: 9000, cache_creation_tokens: 100, cost_usd: 0.1, model_primary: 'claude-opus-4-7' },
      { input_tokens: 100, cache_read_tokens: 9000, cache_creation_tokens: 100, cost_usd: 0.1, model_primary: 'claude-opus-4-7' },
    ];
    const sessions = [
      { input_tokens: 5000, cache_read_tokens: 1000, cache_creation_tokens: 5000, cost_usd: 0.5, model_primary: 'claude-opus-4-7', session_uuid: 'x', message_count: 5 },
      { input_tokens: 5000, cache_read_tokens: 1000, cache_creation_tokens: 5000, cost_usd: 0.5, model_primary: 'claude-opus-4-7', session_uuid: 'y', message_count: 5 },
    ];
    const memo = generateMemo({
      project,
      sessions,
      priorSessions,
      findings: [],
      stuckLoopTotal: 0,
      now: new Date('2026-05-12T00:00:00Z'),
    });
    expect(memo.markdown).toMatch(/Cache hit rate dropped/);
    expect(memo.summary.deltaPP).toBeLessThan(-10);
  });

  it('generateMemo handles a window with zero sessions', () => {
    const project = { id: 1, slug: 'empty' };
    const memo = generateMemo({
      project,
      sessions: [],
      priorSessions: [],
      findings: [],
      stuckLoopTotal: 0,
      now: new Date('2026-05-12T00:00:00Z'),
    });
    expect(memo.markdown).toMatch(/No sessions this week/);
    expect(memo.summary.sessions).toBe(0);
  });
});
