import { describe, test, expect } from 'vitest';
import { dedupePostsByShortcode, filterSince, hasPostBefore, sortByUploadedAtDesc } from './pagination.js';
import type { ScrapedPost } from './types.js';

const post = (shortcode: string, uploadedAt: string, commentCount = 0): ScrapedPost => ({
  shortcode,
  type: 'reel',
  url: `https://www.instagram.com/reel/${shortcode}/`,
  thumbnail: null,
  caption: null,
  uploadedAt,
  viewCount: null,
  likeCount: null,
  commentCount,
});

describe('dedupePostsByShortcode', () => {
  test('keeps one post per shortcode, last occurrence wins', () => {
    const out = dedupePostsByShortcode([
      post('A', '2026-01-01T00:00:00.000Z', 1),
      post('B', '2026-01-02T00:00:00.000Z'),
      post('A', '2026-01-01T00:00:00.000Z', 5),
    ]);
    expect(out).toHaveLength(2);
    expect(out.find((p) => p.shortcode === 'A')!.commentCount).toBe(5);
  });

  test('preserves order of first appearance', () => {
    const out = dedupePostsByShortcode([post('B', '2026-01-02T00:00:00.000Z'), post('A', '2026-01-01T00:00:00.000Z')]);
    expect(out.map((p) => p.shortcode)).toEqual(['B', 'A']);
  });
});

describe('filterSince', () => {
  test('keeps posts uploaded on or after the cutoff', () => {
    const out = filterSince(
      [post('old', '2025-12-01T00:00:00.000Z'), post('new', '2026-02-01T00:00:00.000Z')],
      '2026-01-01T00:00:00.000Z',
    );
    expect(out.map((p) => p.shortcode)).toEqual(['new']);
  });
});

describe('hasPostBefore', () => {
  test('true when any post predates the cutoff', () => {
    expect(
      hasPostBefore([post('a', '2026-02-01T00:00:00.000Z'), post('b', '2025-11-01T00:00:00.000Z')], '2026-01-01T00:00:00.000Z'),
    ).toBe(true);
  });

  test('false when all posts are at/after the cutoff', () => {
    expect(hasPostBefore([post('a', '2026-02-01T00:00:00.000Z')], '2026-01-01T00:00:00.000Z')).toBe(false);
  });
});

describe('sortByUploadedAtDesc', () => {
  test('orders newest first (pinned-old posts do not stay on top)', () => {
    const mk = (shortcode: string, iso: string) =>
      ({ shortcode, type: 'reel', url: '', thumbnail: null, caption: null, uploadedAt: iso, viewCount: null, likeCount: null, commentCount: 0 }) as const;
    const out = sortByUploadedAtDesc([
      mk('pinnedOld', '2025-01-01T00:00:00Z'),
      mk('new', '2026-06-20T00:00:00Z'),
      mk('mid', '2026-03-01T00:00:00Z'),
    ]);
    expect(out.map((p) => p.shortcode)).toEqual(['new', 'mid', 'pinnedOld']);
  });
});
