/**
 * reportRateLimiter.ts 단위 테스트
 *
 * 테스트 대상:
 *  - checkDocumentRateLimit : 문서 레벨 24h rate limit
 *  - checkGlobalRateLimit   : 글로벌 24h rate limit (최대 10건)
 *
 * vitest로 실행. Firestore mock 사용.
 */

import { describe, it, expect, vi } from 'vitest';
import {
  checkDocumentRateLimit,
  checkGlobalRateLimit,
} from '../reportRateLimiter';

// ── Firestore mock 헬퍼 ───────────────────────────────────────────────────────

/**
 * documents/{docId}/reports 서브컬렉션 mock.
 * docs 배열로 스냅샷을 시뮬레이션.
 */
function makeDocReportsMockDb(docs: { createdAt: Date }[]) {
  const mockQuery = {
    where: vi.fn().mockReturnThis(),
    get: vi.fn().mockResolvedValue({
      empty: docs.length === 0,
      size: docs.length,
      docs: docs.map((d) => ({
        data: () => ({
          createdAt: {
            toDate: () => d.createdAt,
          },
        }),
      })),
    }),
  };

  return {
    collection: vi.fn(() => ({
      doc: vi.fn(() => ({
        collection: vi.fn(() => mockQuery),
      })),
    })),
  } as never;
}

/**
 * collectionGroup('reports') mock.
 * count로 스냅샷 size를 시뮬레이션.
 */
function makeGlobalReportsMockDb(count: number) {
  const mockQuery = {
    where: vi.fn().mockReturnThis(),
    limit: vi.fn().mockReturnThis(),
    get: vi.fn().mockResolvedValue({
      size: count,
    }),
  };

  return {
    collectionGroup: vi.fn(() => mockQuery),
  } as never;
}

// ── checkDocumentRateLimit 테스트 ─────────────────────────────────────────────

describe('checkDocumentRateLimit - 문서 레벨 rate limit', () => {
  it('24h 내 기존 신고 있음 → allowed: false', async () => {
    // 1시간 전 신고
    const recentDate = new Date(Date.now() - 1 * 60 * 60 * 1000);
    const db = makeDocReportsMockDb([{ createdAt: recentDate }]);

    const result = await checkDocumentRateLimit('user-1', 'doc-1', db);

    expect(result.allowed).toBe(false);
    expect(result.retryAfterMs).toBeGreaterThan(0);
  });

  it('24h 내 기존 신고 없음 → allowed: true', async () => {
    const db = makeDocReportsMockDb([]);

    const result = await checkDocumentRateLimit('user-1', 'doc-1', db);

    expect(result.allowed).toBe(true);
    expect(result.retryAfterMs).toBeUndefined();
  });

  it('정확히 24h 전 신고 (경계값) → allowed: true', async () => {
    // Firestore 쿼리가 createdAt > 24h전 이므로, 24h 전 신고는 쿼리 결과에 포함 안 됨
    // mock에서 empty: true로 시뮬레이션 (경계값은 쿼리에서 제외됨)
    const db = makeDocReportsMockDb([]);

    const result = await checkDocumentRateLimit('user-1', 'doc-1', db);

    expect(result.allowed).toBe(true);
  });
});

// ── checkGlobalRateLimit 테스트 ──────────────────────────────────────────────

describe('checkGlobalRateLimit - 글로벌 rate limit', () => {
  it('10건 신고 후 → allowed: false, remaining: 0', async () => {
    const db = makeGlobalReportsMockDb(10);

    const result = await checkGlobalRateLimit('user-1', db);

    expect(result.allowed).toBe(false);
    expect(result.remaining).toBe(0);
  });

  it('9건 신고 후 → allowed: true, remaining: 1', async () => {
    const db = makeGlobalReportsMockDb(9);

    const result = await checkGlobalRateLimit('user-1', db);

    expect(result.allowed).toBe(true);
    expect(result.remaining).toBe(1);
  });

  it('0건 → allowed: true, remaining: 10', async () => {
    const db = makeGlobalReportsMockDb(0);

    const result = await checkGlobalRateLimit('user-1', db);

    expect(result.allowed).toBe(true);
    expect(result.remaining).toBe(10);
  });
});
