package dto

import (
	"testing"
)

// --- GetPage ---

func TestGetPage_Zero_Returns1(t *testing.T) {
	p := &PaginationParams{Page: 0}
	if got := p.GetPage(); got != 1 {
		t.Errorf("GetPage(0) = %d, want 1", got)
	}
}

func TestGetPage_Negative_Returns1(t *testing.T) {
	p := &PaginationParams{Page: -5}
	if got := p.GetPage(); got != 1 {
		t.Errorf("GetPage(-5) = %d, want 1", got)
	}
}

func TestGetPage_Valid_ReturnsValue(t *testing.T) {
	p := &PaginationParams{Page: 3}
	if got := p.GetPage(); got != 3 {
		t.Errorf("GetPage(3) = %d, want 3", got)
	}
}

// --- GetPerPage ---

func TestGetPerPage_Zero_Returns20(t *testing.T) {
	p := &PaginationParams{PerPage: 0}
	if got := p.GetPerPage(); got != 20 {
		t.Errorf("GetPerPage(0) = %d, want 20", got)
	}
}

func TestGetPerPage_Negative_Returns20(t *testing.T) {
	p := &PaginationParams{PerPage: -1}
	if got := p.GetPerPage(); got != 20 {
		t.Errorf("GetPerPage(-1) = %d, want 20", got)
	}
}

func TestGetPerPage_TooLarge_Returns10000(t *testing.T) {
	p := &PaginationParams{PerPage: 20000}
	if got := p.GetPerPage(); got != 10000 {
		t.Errorf("GetPerPage(20000) = %d, want 10000", got)
	}
}

func TestGetPerPage_Valid_ReturnsValue(t *testing.T) {
	p := &PaginationParams{PerPage: 50}
	if got := p.GetPerPage(); got != 50 {
		t.Errorf("GetPerPage(50) = %d, want 50", got)
	}
}

// --- GetOffset ---

func TestGetOffset_Page1_Returns0(t *testing.T) {
	p := &PaginationParams{Page: 1, PerPage: 20}
	if got := p.GetOffset(); got != 0 {
		t.Errorf("GetOffset(page=1, perPage=20) = %d, want 0", got)
	}
}

func TestGetOffset_Page3_PerPage10_Returns20(t *testing.T) {
	p := &PaginationParams{Page: 3, PerPage: 10}
	if got := p.GetOffset(); got != 20 {
		t.Errorf("GetOffset(page=3, perPage=10) = %d, want 20", got)
	}
}

func TestGetOffset_Defaults_Returns0(t *testing.T) {
	p := &PaginationParams{}
	if got := p.GetOffset(); got != 0 {
		t.Errorf("GetOffset(defaults) = %d, want 0", got)
	}
}

// --- GetSortDir ---

func TestGetSortDir_Asc(t *testing.T) {
	p := &PaginationParams{SortDir: "asc"}
	if got := p.GetSortDir(); got != "ASC" {
		t.Errorf("GetSortDir('asc') = %q, want 'ASC'", got)
	}
}

func TestGetSortDir_Desc(t *testing.T) {
	p := &PaginationParams{SortDir: "desc"}
	if got := p.GetSortDir(); got != "DESC" {
		t.Errorf("GetSortDir('desc') = %q, want 'DESC'", got)
	}
}

func TestGetSortDir_Empty_ReturnsDesc(t *testing.T) {
	p := &PaginationParams{SortDir: ""}
	if got := p.GetSortDir(); got != "DESC" {
		t.Errorf("GetSortDir('') = %q, want 'DESC'", got)
	}
}

func TestGetSortDir_Invalid_ReturnsDesc(t *testing.T) {
	p := &PaginationParams{SortDir: "RANDOM"}
	if got := p.GetSortDir(); got != "DESC" {
		t.Errorf("GetSortDir('RANDOM') = %q, want 'DESC'", got)
	}
}

// --- GetSafeSortBy ---

func TestGetSafeSortBy_Allowed(t *testing.T) {
	p := &PaginationParams{SortBy: "name"}
	got := p.GetSafeSortBy([]string{"name", "email"}, "id")
	if got != "name" {
		t.Errorf("GetSafeSortBy('name') = %q, want 'name'", got)
	}
}

func TestGetSafeSortBy_NotAllowed_ReturnsDefault(t *testing.T) {
	p := &PaginationParams{SortBy: "password"}
	got := p.GetSafeSortBy([]string{"name", "email"}, "id")
	if got != "id" {
		t.Errorf("GetSafeSortBy('password') = %q, want 'id'", got)
	}
}

func TestGetSafeSortBy_Empty_ReturnsDefault(t *testing.T) {
	p := &PaginationParams{SortBy: ""}
	got := p.GetSafeSortBy([]string{"name", "email"}, "id")
	if got != "id" {
		t.Errorf("GetSafeSortBy('') = %q, want 'id'", got)
	}
}

// --- NewPaginatedResponse ---

func TestNewPaginatedResponse_ExactPages(t *testing.T) {
	resp := NewPaginatedResponse([]string{"a", "b"}, 40, 1, 20)
	if resp.TotalPages != 2 {
		t.Errorf("TotalPages = %d, want 2", resp.TotalPages)
	}
	if resp.Total != 40 {
		t.Errorf("Total = %d, want 40", resp.Total)
	}
	if resp.Page != 1 {
		t.Errorf("Page = %d, want 1", resp.Page)
	}
	if resp.PerPage != 20 {
		t.Errorf("PerPage = %d, want 20", resp.PerPage)
	}
}

func TestNewPaginatedResponse_PartialLastPage(t *testing.T) {
	resp := NewPaginatedResponse(nil, 21, 1, 20)
	if resp.TotalPages != 2 {
		t.Errorf("TotalPages = %d, want 2", resp.TotalPages)
	}
}

func TestNewPaginatedResponse_SinglePage(t *testing.T) {
	resp := NewPaginatedResponse(nil, 5, 1, 20)
	if resp.TotalPages != 1 {
		t.Errorf("TotalPages = %d, want 1", resp.TotalPages)
	}
}

func TestNewPaginatedResponse_ZeroTotal(t *testing.T) {
	resp := NewPaginatedResponse(nil, 0, 1, 20)
	if resp.TotalPages != 0 {
		t.Errorf("TotalPages = %d, want 0", resp.TotalPages)
	}
}
