package restdemo

import (
	"crypto/sha256"
	"errors"
	"fmt"
	"slices"
	"sync"
	"testing"
)

func Example_pagination() {
	rows := []int{1, 2, 3, 4}
	fmt.Println("first:", rows[:2])
	rows = append([]int{0}, rows...)
	fmt.Println("offset=2:", rows[2:4])
	after := slices.DeleteFunc(slices.Clone(rows), func(id int) bool { return id <= 2 })
	fmt.Println("after=2:", after[:2])
	// Output:
	// first: [1 2]
	// offset=2: [2 3]
	// after=2: [3 4]
}

type result struct {
	digest [32]byte
	id     int
}
type deduper struct {
	mu      sync.Mutex
	next    int
	entries map[string]result
}

func (d *deduper) create(key, body string) (int, bool, error) {
	d.mu.Lock()
	defer d.mu.Unlock()
	digest := sha256.Sum256([]byte(body))
	if old, ok := d.entries[key]; ok {
		if old.digest != digest {
			return 0, false, errors.New("key reused with different input")
		}
		return old.id, true, nil
	}
	d.next++
	if d.entries == nil {
		d.entries = make(map[string]result)
	}
	d.entries[key] = result{digest: digest, id: d.next}
	return d.next, false, nil
}
func Example_idempotency() {
	d := new(deduper)
	for _, input := range []string{"book", "book", "pen"} {
		id, replay, err := d.create("user-7:key-1", input)
		fmt.Printf("id=%d replay=%v error=%v\n", id, replay, err != nil)
	}
	// Output:
	// id=1 replay=false error=false
	// id=1 replay=true error=false
	// id=0 replay=false error=true
}
func TestConcurrentDedup(t *testing.T) {
	d := new(deduper)
	var wg sync.WaitGroup
	for range 20 {
		wg.Go(func() {
			id, _, err := d.create("same", "book")
			if id != 1 || err != nil {
				t.Errorf("id=%d err=%v", id, err)
			}
		})
	}
	wg.Wait()
	if d.next != 1 {
		t.Fatal(d.next)
	}
}
