<?php

/**
 * JCOGS Image Pro - Validation Result
 * ====================================
 * Immutable value object for validation results
 * 
 * @category   ExpressionEngine Add-on
 * @package    JCOGS Image Pro
 * @author     JCOGS Design <contact@jcogs.net>
 * @copyright  Copyright (c) 2021 - 2025 JCOGS Design
 * @license    https://jcogs.net/add-ons/license/jcogs_img_pro
 * @version    2.0.6
 * @link       https://JCOGS.net/
 * @since      2.0.0
 */

namespace JCOGSDesign\JCOGSImagePro\Service\Validation;

/**
 * Validation Result
 * 
 * Immutable value object representing the result of a validation operation.
 * 
 * This object is returned by all validators implementing ValidatorInterface.
 * It provides a consistent interface for checking validation success/failure
 * and accessing sanitized values or error messages.
 * 
 * Example Usage:
 * 
 * ```php
 * // Success case
 * $result = ValidationResult::success(100);
 * if ($result->success) {
 *     echo "Value: " . $result->sanitizedValue; // 100
 * }
 * 
 * // Error case
 * $result = ValidationResult::error("Value must be between 1 and 100", 150);
 * if (!$result->success) {
 *     echo $result->error; // "Value must be between 1 and 100"
 *     echo $result->sanitizedValue; // 150 (original value preserved)
 * }
 * ```
 * 
 * Immutability:
 * 
 * Properties are readonly (PHP 8.1+). Once created, the object cannot be modified.
 * This ensures validation results remain consistent throughout the request lifecycle.
 * 
 * @package JCOGSDesign\JCOGSImagePro\Service\Validation
 * @since 2.0.0
 */
class ValidationResult
{
    /**
     * Validation success status
     * 
     * @var bool True if validation passed, false if failed
     */
    public readonly bool $success;
    
    /**
     * Sanitized value
     * 
     * On success: The sanitized/normalized value (e.g., lowercase enum, normalized percentage)
     * On failure: The original value that failed validation
     * 
     * @var mixed
     */
    public readonly mixed $sanitizedValue;
    
    /**
     * Error message
     * 
     * Null on success, descriptive error message on failure.
     * 
     * @var string|null
     */
    public readonly ?string $error;
    
    /**
     * Private constructor - use static factories instead
     * 
     * @param bool $success Validation success status
     * @param mixed $sanitizedValue Sanitized value (success) or original value (failure)
     * @param string|null $error Error message (null on success)
     */
    private function __construct(bool $success, mixed $sanitizedValue, ?string $error = null)
    {
        $this->success = $success;
        $this->sanitizedValue = $sanitizedValue;
        $this->error = $error;
    }
    
    /**
     * Create successful validation result
     * 
     * @param mixed $sanitizedValue The sanitized/normalized value to return
     * 
     * @return self Success result with sanitizedValue and no error
     */
    public static function success(mixed $sanitizedValue): self
    {
        return new self(true, $sanitizedValue, null);
    }
    
    /**
     * Create failed validation result
     * 
     * @param string $message Descriptive error message
     * @param mixed $originalValue The original value that failed validation (preserved for debugging)
     * 
     * @return self Error result with error message and original value
     */
    public static function error(string $message, mixed $originalValue = null): self
    {
        return new self(false, $originalValue, $message);
    }
}
