package apicontract

import (
	"encoding/base64"
	"errors"
	"fmt"
	"hash/crc32"
	"strconv"
	"strings"
)

// Cursors implement opaque, tamper-evident pagination. The client treats
// the cursor as a blob; the server encodes the position and a checksum so
// a mangled cursor is rejected rather than silently returning wrong data.
// Opaque cursors let you change the pagination implementation (offset →
// keyset) without breaking the contract — the API design point.

// EncodeCursor produces an opaque cursor for a position (here, an offset).
func EncodeCursor(offset int) string {
	payload := fmt.Sprintf("%d", offset)
	sum := crc32.ChecksumIEEE([]byte(payload))
	blob := fmt.Sprintf("%s|%08x", payload, sum)
	return base64.RawURLEncoding.EncodeToString([]byte(blob))
}

// DecodeCursor parses a cursor, rejecting tampered/garbage values.
func DecodeCursor(cursor string) (int, error) {
	if cursor == "" {
		return 0, nil // start of the collection
	}
	raw, err := base64.RawURLEncoding.DecodeString(cursor)
	if err != nil {
		return 0, errors.New("apicontract: malformed cursor")
	}
	parts := strings.Split(string(raw), "|")
	if len(parts) != 2 {
		return 0, errors.New("apicontract: malformed cursor")
	}
	offset, err := strconv.Atoi(parts[0])
	if err != nil {
		return 0, errors.New("apicontract: malformed cursor")
	}
	want := fmt.Sprintf("%08x", crc32.ChecksumIEEE([]byte(parts[0])))
	if parts[1] != want {
		return 0, errors.New("apicontract: cursor checksum mismatch (tampered)")
	}
	return offset, nil
}
