package main

import (
	"crypto/rand"
	"fmt"
	"time"

	"github.com/oklog/ulid/v2"
)

func main() {
	// Generate a new ULID with current timestamp
	id := ulid.Make()
	fmt.Println("New ULID:", id) // e.g., 01ARZ3NDEKTSV4RRFFQ69G5FAV

	// ULIDs are lexicographically sortable
	// Earlier timestamps sort before later ones
	time.Sleep(time.Millisecond)
	id2 := ulid.Make()
	fmt.Println("Later ULID:", id2)
	fmt.Println("id < id2:", id.String() < id2.String()) // true

	// ULID structure: timestamp (48 bits) + randomness (80 bits)
	fmt.Println("Timestamp:", ulid.Time(id.Time()))

	// Generate with explicit entropy source
	entropy := ulid.Monotonic(rand.Reader, 0)
	id3, err := ulid.New(ulid.Timestamp(time.Now()), entropy)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("With entropy:", id3)

	// Parse ULID from string
	parsed, err := ulid.Parse("01ARZ3NDEKTSV4RRFFQ69G5FAV")
	if err != nil {
		fmt.Println("Parse error:", err)
		return
	}
	fmt.Println("Parsed:", parsed)

	// Strict parsing (rejects lowercase)
	_, err = ulid.ParseStrict("01arz3ndektsv4rrffq69g5fav")
	if err != nil {
		fmt.Println("Strict parse error:", err) // lowercase not allowed
	}

	// Convert to/from bytes
	bytes := id.Bytes()
	fmt.Println("Bytes length:", len(bytes)) // 16 bytes

	// Compare ULIDs
	fmt.Println("Same ULID:", id.Compare(id) == 0)  // true
	fmt.Println("id before id2:", id.Compare(id2)) // -1

	// MustParse - panics on invalid (useful for constants)
	knownID := ulid.MustParse("01ARZ3NDEKTSV4RRFFQ69G5FAV")
	fmt.Println("Known ID:", knownID)

	// Zero ULID check
	var zeroID ulid.ULID
	fmt.Println("Is zero:", zeroID.Compare(ulid.ULID{}) == 0) // true

	// Extract timestamp from existing ULID
	ts := ulid.Time(id.Time())
	fmt.Println("Created at:", ts)
}
