package main

import (
	"fmt"

	"github.com/samber/lo"
)

// User represents a user in the system
type User struct {
	ID     int
	Name   string
	Age    int
	Active bool
}

func main() {
	// Filter - keep only elements matching predicate
	nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	evens := lo.Filter(nums, func(n int, _ int) bool {
		return n%2 == 0
	})
	fmt.Println("Evens:", evens) // [2, 4, 6, 8, 10]

	// Map - transform each element
	doubled := lo.Map(nums, func(n int, _ int) int {
		return n * 2
	})
	fmt.Println("Doubled:", doubled) // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

	// Reduce - aggregate to single value
	sum := lo.Reduce(nums, func(acc int, n int, _ int) int {
		return acc + n
	}, 0)
	fmt.Println("Sum:", sum) // 55

	// Find - get first matching element
	users := []User{
		{1, "Alice", 30, true},
		{2, "Bob", 25, false},
		{3, "Charlie", 35, true},
	}
	user, found := lo.Find(users, func(u User) bool {
		return u.Name == "Bob"
	})
	fmt.Printf("Found Bob: %v (%v)\n", user, found)

	// Uniq - remove duplicates
	items := []string{"a", "b", "a", "c", "b", "d"}
	unique := lo.Uniq(items)
	fmt.Println("Unique:", unique) // [a, b, c, d]

	// GroupBy - group elements by key
	byActive := lo.GroupBy(users, func(u User) bool {
		return u.Active
	})
	fmt.Println("Active users:", byActive[true])
	fmt.Println("Inactive users:", byActive[false])

	// Chunk - split into smaller slices
	chunks := lo.Chunk(nums, 3)
	fmt.Println("Chunks:", chunks) // [[1 2 3] [4 5 6] [7 8 9] [10]]

	// Contains - check if slice contains element
	hasThree := lo.Contains(nums, 3)
	fmt.Println("Contains 3:", hasThree) // true

	// Keys and Values from maps
	m := map[string]int{"a": 1, "b": 2, "c": 3}
	keys := lo.Keys(m)
	values := lo.Values(m)
	fmt.Println("Keys:", keys)     // [a b c] (order may vary)
	fmt.Println("Values:", values) // [1 2 3] (order may vary)

	// Ternary - inline conditional
	status := lo.Ternary(true, "active", "inactive")
	fmt.Println("Status:", status) // active

	// Must - panic on error (useful in init or tests)
	// val := lo.Must(strconv.Atoi("42")) // returns 42 or panics

	// Coalesce - return first non-zero value
	first := lo.Coalesce("", "", "hello", "world")
	fmt.Println("First non-empty:", first) // hello

	// FilterMap - filter and transform in one pass
	activeNames := lo.FilterMap(users, func(u User, _ int) (string, bool) {
		return u.Name, u.Active
	})
	fmt.Println("Active names:", activeNames) // [Alice Charlie]
}
