<?php

declare(strict_types=1);

namespace App\Support;

/**
 * RouteArgumentParser handles parsing URL arguments in format: "page-name--h:HASHKEY" or "page-name--e:ENCODED_PAYLOAD"
 */
class RouteArgumentParser
{
    /**
     * Parse a route argument string into its components
     * 
     * @param string $argument The route argument string (e.g., "edituser--h:USER_HASH123")
     * @return array {slug: string, type?: 'hash'|'payload', value?: string} Array with parsed components
     */
    public function parseArgument($argument)
    {
        if (!is_string($argument) || empty($argument)) {
            return [
                'slug' => $argument,
                'type' => null,
                'value' => null
            ];
        }

        // Check for hash format: --h:HASHKEY
        if (preg_match('/^(.*?)--h:(.*)$/', $argument, $matches)) {
            return [
                'slug' => $matches[1],
                'type' => 'hash',
                'value' => $this->decodeHashValue($matches[2])
            ];
        }

        // Check for payload format: --e:ENCODED_PAYLOAD
        if (preg_match('/^(.*?)--e:(.*)$/', $argument, $matches)) {
            return [
                'slug' => $matches[1],
                'type' => 'payload',
                'value' => $this->decodePayloadValue($matches[2])
            ];
        }

        // Backward compatibility: Check for hash format without colon: --hHASHKEY
        if (preg_match('/^(.*?)--h([^:].*)$/', $argument, $matches)) {
            return [
                'slug' => $matches[1],
                'type' => 'hash',
                'value' => $this->decodeHashValue($matches[2])
            ];
        }

        // No hash/payload found - just return the slug
        return [
            'slug' => $argument,
            'type' => null,
            'value' => null
        ];
    }

    /**
     * Decode a hash value from URL format (base64 encoded)
     */
    private function decodeHashValue($encodedValue)
    {
        if (!is_string($encodedValue) || empty($encodedValue)) {
            return $encodedValue;
        }

        try {
            // Remove base64 encoding and decode
            $decoded = base64_decode($encodedValue, true);
            
            // If it's valid UTF-8 string representation of the hashkey
            if (is_string($decoded) && mb_check_encoding($decoded, 'utf-8')) {
                // Frontend encodes as btoa(encodeURIComponent(hashkey)),
                // so we need to urldecode after base64_decode
                return urldecode($decoded);
            }
            
            return $encodedValue; // Return original if decoding fails
        } catch (\Exception $e) {
            error_log('[RouteArgumentParser] Error decoding hash: ' . $e->getMessage());
            return null;
        }
    }

    /**
     * Decode a payload value from URL format (base64 encoded JSON)
     */
    private function decodePayloadValue($encodedValue)
    {
        if (!is_string($encodedValue) || empty($encodedValue)) {
            return null;
        }

        try {
            // Remove base64 encoding and decode
            $decoded = base64_decode($encodedValue, true);
            
            // Decode URI components if it was encoded on frontend
            if ($decoded) {
                $decoded = urldecode($decoded);
            }

            // Parse JSON
            $jsonData = json_decode($decoded, true);
            
            if (json_last_error() === JSON_ERROR_NONE) {
                return $jsonData;
            }
            
            return null;
        } catch (\Exception $e) {
            error_log('[RouteArgumentParser] Error decoding payload: ' . $e->getMessage());
            return null;
        }
    }

    /**
     * Check if argument contains hash format
     */
    public function isHashFormat($argument)
    {
        return (bool) preg_match('/^(.*?)--h:?(.*)$/', $argument, $matches);
    }

    /**
     * Check if argument contains payload format
     */
    public function isPayloadFormat($argument)
    {
        return (bool) preg_match('/^(.*?)--e:(.*)$/', $argument, $matches);
    }
}