package uuid

import (
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"time"
)

// V7 generates a UUID v7 (time-ordered) following RFC 9562
// Format: tttttttt-tttt-7xxx-yxxx-xxxxxxxxxxxx
// Where: t = timestamp (48 bits), 7 = version, y = variant, x = random
func V7() string {
	// Get current timestamp in milliseconds
	timestamp := time.Now().UnixMilli()

	// Generate 10 random bytes
	randomBytes := make([]byte, 10)
	rand.Read(randomBytes)

	// Build UUID bytes (16 total)
	var bytes [16]byte

	// First 6 bytes: timestamp (48 bits, big-endian)
	binary.BigEndian.PutUint32(bytes[0:4], uint32(timestamp>>16))
	binary.BigEndian.PutUint16(bytes[4:6], uint16(timestamp))

	// Next 2 bytes: version (4 bits = 7) + random (12 bits)
	bytes[6] = 0x70 | (randomBytes[0] & 0x0F) // version 7
	bytes[7] = randomBytes[1]

	// Last 8 bytes: variant (2 bits = 10) + random (62 bits)
	bytes[8] = 0x80 | (randomBytes[2] & 0x3F) // variant RFC 4122
	copy(bytes[9:16], randomBytes[3:10])

	// Format as UUID string
	return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
		binary.BigEndian.Uint32(bytes[0:4]),
		binary.BigEndian.Uint16(bytes[4:6]),
		binary.BigEndian.Uint16(bytes[6:8]),
		binary.BigEndian.Uint16(bytes[8:10]),
		bytes[10:16],
	)
}

// IsValid checks if a string is a valid UUID (any version)
func IsValid(s string) bool {
	// Basic UUID format check: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	if len(s) != 36 {
		return false
	}
	for i, c := range s {
		if i == 8 || i == 13 || i == 18 || i == 23 {
			if c != '-' {
				return false
			}
		} else {
			if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
				return false
			}
		}
	}
	return true
}
