import { describe, it, expect } from 'vitest';
import {
  planScreenshotSegments,
  segmentFilename,
  ABSOLUTE_MAX_SEGMENTS,
} from './browser.js';

// Pure segmentation math — no browser required, runs in plain node.
describe('planScreenshotSegments', () => {
  it('returns a single offset when the page fits within one viewport', () => {
    expect(planScreenshotSegments(500, 800, 10)).toEqual([0]);
  });

  it('treats a page exactly one viewport tall as a single segment', () => {
    expect(planScreenshotSegments(800, 800, 10)).toEqual([0]);
  });

  it('splits into two segments when the page is slightly taller than the viewport', () => {
    expect(planScreenshotSegments(900, 800, 10)).toEqual([0, 800]);
  });

  it('produces one offset per viewport-sized slice for a tall page', () => {
    expect(planScreenshotSegments(2500, 1000, 10)).toEqual([0, 1000, 2000]);
  });

  it('does not add a trailing empty segment when height is an exact multiple', () => {
    expect(planScreenshotSegments(2000, 1000, 10)).toEqual([0, 1000]);
  });

  it('caps the number of segments at maxSegments', () => {
    const offsets = planScreenshotSegments(100_000, 1000, 10);
    expect(offsets).toHaveLength(10);
    expect(offsets[0]).toBe(0);
    expect(offsets[9]).toBe(9000);
  });

  it('defensively returns a single segment for a non-positive viewport height', () => {
    expect(planScreenshotSegments(2000, 0, 10)).toEqual([0]);
  });

  it('clamps maxSegments to at least one segment', () => {
    expect(planScreenshotSegments(2500, 1000, 0)).toEqual([0]);
  });

  it('never exceeds ABSOLUTE_MAX_SEGMENTS even with a huge maxSegments', () => {
    const offsets = planScreenshotSegments(1_000_000, 100, 1_000_000);
    expect(offsets).toHaveLength(ABSOLUTE_MAX_SEGMENTS);
  });

  it('never exceeds ABSOLUTE_MAX_SEGMENTS even with a huge page and default cap', () => {
    // A pathological scrollHeight must not blow past the absolute ceiling.
    const offsets = planScreenshotSegments(10_000_000, 100, 999);
    expect(offsets.length).toBeLessThanOrEqual(ABSOLUTE_MAX_SEGMENTS);
  });

  it('falls back to the default cap for a non-finite maxSegments', () => {
    expect(planScreenshotSegments(2500, 1000, Number.NaN)).toEqual([0, 1000, 2000]);
    expect(planScreenshotSegments(2500, 1000, Infinity)).toEqual([0, 1000, 2000]);
  });
});

describe('segmentFilename', () => {
  it('inserts a zero-padded 1-based index before the extension', () => {
    expect(segmentFilename('report.png', 1)).toBe('report-001.png');
    expect(segmentFilename('report.png', 2)).toBe('report-002.png');
  });

  it('pads to three digits and preserves the original extension', () => {
    expect(segmentFilename('shot.jpeg', 12)).toBe('shot-012.jpeg');
  });

  it('defaults to a .png extension when the filename has none', () => {
    expect(segmentFilename('report', 1)).toBe('report-001.png');
  });

  it('splits on the last dot for multi-dot filenames', () => {
    expect(segmentFilename('a.b.png', 1)).toBe('a.b-001.png');
  });

  it('does not truncate indices beyond three digits', () => {
    expect(segmentFilename('x.png', 1000)).toBe('x-1000.png');
  });

  it('only treats a dot in the basename as the extension separator', () => {
    // A dot in a directory segment must not be mistaken for the extension.
    expect(segmentFilename('sub.dir/report', 1)).toBe('sub.dir/report-001.png');
    expect(segmentFilename('v1.2/page.png', 1)).toBe('v1.2/page-001.png');
  });
});
