package pagination

import (
	"math"
	"testing"
)

func TestPageCount(t *testing.T) {
	tests := []struct {
		name           string
		total, perPage int
		want           int
	}{
		{name: "empty", total: 0, perPage: 20, want: 0},
		{name: "partial_last_page", total: 50, perPage: 20, want: 3},
		{name: "maximum_total", total: math.MaxInt, perPage: 100, want: 1 + (math.MaxInt-1)/100},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := PageCount(tt.total, tt.perPage); got != tt.want {
				t.Fatalf("PageCount(%d, %d) = %d, want %d", tt.total, tt.perPage, got, tt.want)
			}
		})
	}
}

func TestOffset(t *testing.T) {
	tests := []struct {
		name          string
		page, perPage int
		want          int
		wantOK        bool
	}{
		{name: "first_page", page: 1, perPage: 100, want: 0, wantOK: true},
		{name: "maximum_page_with_unit_size", page: math.MaxInt, perPage: 1, want: math.MaxInt - 1, wantOK: true},
		{name: "overflow", page: math.MaxInt, perPage: 100, wantOK: false},
		{name: "invalid_page", page: 0, perPage: 100, wantOK: false},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, ok := Offset(tt.page, tt.perPage)
			if got != tt.want || ok != tt.wantOK {
				t.Fatalf("Offset(%d, %d) = (%d, %t), want (%d, %t)", tt.page, tt.perPage, got, ok, tt.want, tt.wantOK)
			}
		})
	}
}

func TestBounds(t *testing.T) {
	tests := []struct {
		name                 string
		total, page, perPage int
		wantStart, wantEnd   int
		wantOK               bool
	}{
		{name: "first_page", total: 10, page: 1, perPage: 3, wantStart: 0, wantEnd: 3, wantOK: true},
		{name: "last_partial_page", total: 10, page: 4, perPage: 3, wantStart: 9, wantEnd: 10, wantOK: true},
		{name: "out_of_range", total: 10, page: 5, perPage: 3, wantOK: false},
		{name: "overflow", total: 10, page: math.MaxInt, perPage: 100, wantOK: false},
		{name: "maximum_boundary", total: math.MaxInt, page: math.MaxInt, perPage: 1, wantStart: math.MaxInt - 1, wantEnd: math.MaxInt, wantOK: true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			start, end, ok := Bounds(tt.total, tt.page, tt.perPage)
			if start != tt.wantStart || end != tt.wantEnd || ok != tt.wantOK {
				t.Fatalf("Bounds(%d, %d, %d) = (%d, %d, %t), want (%d, %d, %t)", tt.total, tt.page, tt.perPage, start, end, ok, tt.wantStart, tt.wantEnd, tt.wantOK)
			}
		})
	}
}
