<?php
/**
 * UUID value object.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Domain\Shared;

/**
 * Validated RFC 4122 UUID.
 */
final class Uuid {
	private string $value;
	/**
	 * Creates a UUID.
	 *
	 * @param string $value UUID string.
	 */
	public function __construct( string $value ) {
		$this->value = $value;
		if ( 1 !== preg_match( '/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $value ) ) {
			throw new \InvalidArgumentException( 'Invalid UUID.' );
		}
	}

	/**
	 * Generates a random version 4 UUID.
	 */
	public static function generate(): self {
		$bytes    = random_bytes( 16 );
		$bytes[6] = chr( ( ord( $bytes[6] ) & 0x0f ) | 0x40 );
		$bytes[8] = chr( ( ord( $bytes[8] ) & 0x3f ) | 0x80 );
		$hex      = bin2hex( $bytes );

		return new self(
			substr( $hex, 0, 8 ) . '-' .
			substr( $hex, 8, 4 ) . '-' .
			substr( $hex, 12, 4 ) . '-' .
			substr( $hex, 16, 4 ) . '-' .
			substr( $hex, 20 )
		);
	}

	/**
	 * String value.
	 */
	public function value(): string {
		return strtolower( $this->value );
	}

	/**
	 * String conversion.
	 */
	public function __toString(): string {
		return $this->value();
	}
}
