<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\ValueObjects;

/**
 * Reserved Action Names - Framework methods that cannot be called as actions
 *
 * Provides type-safe enum of all method names that are reserved by the framework
 * and cannot be invoked as LiveComponent actions from the client.
 *
 * Categories:
 * - LiveComponent Contract Methods
 * - Lifecycle Hooks
 * - Cacheable Interface Methods
 * - File Upload Interface Methods
 * - PHP Magic Methods
 */
enum ReservedActionName: string
{
    // ===== LiveComponent Contract Methods =====
    case GET_ID = 'getId';
    case GET_DATA = 'getData';
    case GET_RENDER_DATA = 'getRenderData';

    // ===== Lifecycle Hooks (LifecycleAware) =====
    case ON_MOUNT = 'onMount';
    case ON_UPDATE = 'onUpdate';
    case ON_DESTROY = 'onDestroy';

    // ===== Cacheable Interface Methods =====
    case SHOULD_CACHE = 'shouldCache';
    case GET_CACHE_TTL = 'getCacheTTL';
    case GET_CACHE_KEY = 'getCacheKey';
    case GET_CACHE_TAGS = 'getCacheTags';

    // ===== SupportsFileUpload Interface Methods =====
    case VALIDATE_UPLOAD = 'validateUpload';
    case HANDLE_UPLOAD = 'handleUpload';

    // ===== PHP Magic Methods =====
    case CONSTRUCT = '__construct';
    case DESTRUCT = '__destruct';
    case CALL = '__call';
    case CALL_STATIC = '__callStatic';
    case GET = '__get';
    case SET = '__set';
    case ISSET = '__isset';
    case UNSET = '__unset';
    case SLEEP = '__sleep';
    case WAKEUP = '__wakeup';
    case SERIALIZE = '__serialize';
    case UNSERIALIZE = '__unserialize';
    case TO_STRING = '__toString';
    case INVOKE = '__invoke';
    case SET_STATE = '__set_state';
    case CLONE = '__clone';
    case DEBUG_INFO = '__debugInfo';

    /**
     * Check if a method name is reserved
     */
    public static function isReserved(string $methodName): bool
    {
        return self::tryFrom($methodName) !== null;
    }

    /**
     * Get all reserved method names as array
     *
     * @return array<string>
     */
    public static function values(): array
    {
        return array_map(fn ($case) => $case->value, self::cases());
    }

    /**
     * Get reserved methods by category
     *
     * @return array<string, array<string>>
     */
    public static function byCategory(): array
    {
        return [
            'LiveComponent Contract' => [
                self::GET_ID->value,
                self::GET_DATA->value,
                self::GET_RENDER_DATA->value,
            ],
            'Lifecycle Hooks' => [
                self::ON_MOUNT->value,
                self::ON_UPDATE->value,
                self::ON_DESTROY->value,
            ],
            'Cacheable Interface' => [
                self::SHOULD_CACHE->value,
                self::GET_CACHE_TTL->value,
                self::GET_CACHE_KEY->value,
                self::GET_CACHE_TAGS->value,
            ],
            'File Upload Interface' => [
                self::VALIDATE_UPLOAD->value,
                self::HANDLE_UPLOAD->value,
            ],
            'PHP Magic Methods' => [
                self::CONSTRUCT->value,
                self::DESTRUCT->value,
                self::CALL->value,
                self::CALL_STATIC->value,
                self::GET->value,
                self::SET->value,
                self::ISSET->value,
                self::UNSET->value,
                self::SLEEP->value,
                self::WAKEUP->value,
                self::SERIALIZE->value,
                self::UNSERIALIZE->value,
                self::TO_STRING->value,
                self::INVOKE->value,
                self::SET_STATE->value,
                self::CLONE->value,
                self::DEBUG_INFO->value,
            ],
        ];
    }

    /**
     * Get the category this reserved method belongs to
     */
    public function getCategory(): string
    {
        return match ($this) {
            self::GET_ID, self::GET_DATA, self::GET_RENDER_DATA
                => 'LiveComponent Contract',

            self::ON_MOUNT, self::ON_UPDATE, self::ON_DESTROY
                => 'Lifecycle Hooks',

            self::SHOULD_CACHE, self::GET_CACHE_TTL, self::GET_CACHE_KEY, self::GET_CACHE_TAGS
                => 'Cacheable Interface',

            self::VALIDATE_UPLOAD, self::HANDLE_UPLOAD
                => 'File Upload Interface',

            default => 'PHP Magic Methods',
        };
    }

    /**
     * Get user-friendly error message explaining why this method is reserved
     */
    public function getReasonMessage(): string
    {
        return match ($this->getCategory()) {
            'LiveComponent Contract' => 'Framework contract method - used internally for component lifecycle',
            'Lifecycle Hooks' => 'Lifecycle hook - called automatically by framework, not invokable as action',
            'Cacheable Interface' => 'Caching interface method - used for cache configuration, not an action',
            'File Upload Interface' => 'File upload interface method - use upload endpoint instead',
            'PHP Magic Methods' => 'PHP magic method - cannot be invoked as action',
            default => 'Reserved method - cannot be called as action',
        };
    }
}
