<?php

declare(strict_types=1);

namespace App\Framework\Exception\Core;

use App\Framework\Exception\ErrorCode;

/**
 * Value Object error codes
 *
 * Covers value object validation, construction, and transformation
 */
enum ValueObjectErrorCode: string implements ErrorCode
{
    case INVALID_VALUE = 'VO001';
    case VALIDATION_FAILED = 'VO002';
    case TRANSFORMATION_FAILED = 'VO003';
    case IMMUTABILITY_VIOLATION = 'VO004';

    public function getValue(): string
    {
        return $this->value;
    }

    public function getCategory(): string
    {
        return 'VO';
    }

    public function getNumericCode(): int
    {
        return (int) substr($this->value, -3);
    }

    public function getSeverity(): ErrorSeverity
    {
        return match($this) {
            self::IMMUTABILITY_VIOLATION => ErrorSeverity::CRITICAL,

            self::INVALID_VALUE,
            self::VALIDATION_FAILED,
            self::TRANSFORMATION_FAILED => ErrorSeverity::ERROR,
        };
    }

    public function getDescription(): string
    {
        return match($this) {
            self::INVALID_VALUE => 'Value object contains invalid value',
            self::VALIDATION_FAILED => 'Value object validation failed',
            self::TRANSFORMATION_FAILED => 'Value object transformation failed',
            self::IMMUTABILITY_VIOLATION => 'Attempt to modify immutable value object',
        };
    }

    public function getRecoveryHint(): string
    {
        return match($this) {
            self::INVALID_VALUE => 'Provide valid value according to value object constraints',
            self::VALIDATION_FAILED => 'Review validation rules and correct input',
            self::TRANSFORMATION_FAILED => 'Check transformation logic and input format',
            self::IMMUTABILITY_VIOLATION => 'Create new value object instance instead of modifying',
        };
    }

    public function isRecoverable(): bool
    {
        return match($this) {
            self::IMMUTABILITY_VIOLATION => false,
            default => true,
        };
    }

    public function getRetryAfterSeconds(): ?int
    {
        return null;
    }
}
