/**
 * Analytics Rollups module — unit tests.
 */

import { describe, it, expect } from 'vitest';
import { IngestMetricSchema, IngestBatchSchema, QueryRollupsSchema } from './types.js';
import { toDailyKey, toWeeklyKey, toMonthlyKey, getDateKey } from './repository.js';

// ── Schema Validation ────────────────────────────────────────

describe('IngestMetricSchema', () => {
  it('accepts valid metric with defaults', () => {
    const result = IngestMetricSchema.parse({ metric: 'signups' });
    expect(result.metric).toBe('signups');
    expect(result.value).toBe(1);
    expect(result.timestamp).toBeUndefined();
  });

  it('accepts metric with dots and underscores', () => {
    const result = IngestMetricSchema.parse({ metric: 'user.session_start', value: 5 });
    expect(result.metric).toBe('user.session_start');
    expect(result.value).toBe(5);
  });

  it('rejects empty metric name', () => {
    expect(() => IngestMetricSchema.parse({ metric: '' })).toThrow();
  });

  it('rejects metric with invalid chars', () => {
    expect(() => IngestMetricSchema.parse({ metric: 'BAD-METRIC' })).toThrow();
  });

  it('accepts explicit timestamp', () => {
    const result = IngestMetricSchema.parse({
      metric: 'logins',
      timestamp: '2026-01-15T10:00:00.000Z',
    });
    expect(result.timestamp).toBe('2026-01-15T10:00:00.000Z');
  });
});

describe('IngestBatchSchema', () => {
  it('accepts batch of events', () => {
    const result = IngestBatchSchema.parse({
      events: [
        { metric: 'signups', value: 1 },
        { metric: 'logins', value: 3 },
      ],
    });
    expect(result.events).toHaveLength(2);
  });

  it('rejects empty batch', () => {
    expect(() => IngestBatchSchema.parse({ events: [] })).toThrow();
  });
});

describe('QueryRollupsSchema', () => {
  it('accepts defaults', () => {
    const result = QueryRollupsSchema.parse({});
    expect(result.period).toBe('daily');
  });

  it('accepts all params', () => {
    const result = QueryRollupsSchema.parse({
      period: 'weekly',
      from: '2026-01-01',
      to: '2026-01-31',
      metric: 'signups',
    });
    expect(result.period).toBe('weekly');
    expect(result.metric).toBe('signups');
  });

  it('rejects invalid period', () => {
    expect(() => QueryRollupsSchema.parse({ period: 'yearly' })).toThrow();
  });
});

// ── Date Key Helpers ─────────────────────────────────────────

describe('date key helpers', () => {
  it('toDailyKey returns YYYY-MM-DD', () => {
    expect(toDailyKey(new Date('2026-03-15T10:00:00Z'))).toBe('2026-03-15');
  });

  it('toMonthlyKey returns YYYY-MM', () => {
    expect(toMonthlyKey(new Date('2026-03-15T10:00:00Z'))).toBe('2026-03');
  });

  it('toWeeklyKey returns YYYY-Www format', () => {
    const key = toWeeklyKey(new Date('2026-03-15T10:00:00Z'));
    expect(key).toMatch(/^2026-W\d{2}$/);
  });

  it('getDateKey dispatches correctly', () => {
    const d = new Date('2026-06-01T12:00:00Z');
    expect(getDateKey(d, 'daily')).toBe('2026-06-01');
    expect(getDateKey(d, 'monthly')).toBe('2026-06');
    expect(getDateKey(d, 'weekly')).toMatch(/^2026-W\d{2}$/);
  });
});
