<?php

namespace EasyLinkAutomations\Actions\Discord;

if (!defined('ABSPATH')) {
    exit;
}

final class DiscordRequestHelper
{
    private const API_BASE = 'https://discord.com/api/v10';

    public static function url(string $path, array $query = []): string
    {
        $url = self::API_BASE . '/' . ltrim($path, '/');

        if (!empty($query)) {
            $url .= '?' . http_build_query($query);
        }

        return $url;
    }

    public static function idPath(string ...$segments): string
    {
        return implode('/', array_map('rawurlencode', $segments));
    }

    public static function jsonHeaders(array $authHeaders): array
    {
        return array_merge($authHeaders, ['Content-Type' => 'application/json']);
    }

    public static function emptyBodyHeaders(array $authHeaders): array
    {
        return array_merge($authHeaders, ['Content-Length' => '0']);
    }

    public static function responseBody(mixed $response): mixed
    {
        $raw = wp_remote_retrieve_body($response);
        if ($raw === '') {
            return [];
        }

        $decoded = json_decode($raw, true);

        return json_last_error() === JSON_ERROR_NONE ? $decoded : $raw;
    }

    public static function failureMessage(int $statusCode, mixed $responseBody): string
    {
        $message = 'Unknown error';

        if (is_array($responseBody)) {
            if (isset($responseBody['message'])) {
                $message = (string) $responseBody['message'];
            }

            $detail = self::firstNestedError($responseBody['errors'] ?? null);
            if ($detail !== null) {
                $message .= ': ' . $detail;
            }
        } elseif (is_string($responseBody) && $responseBody !== '') {
            $message = $responseBody;
        }

        return 'Failed (HTTP ' . $statusCode . '): ' . $message;
    }

    public static function limit(mixed $value, int $default, int $max): int
    {
        $limit = is_numeric($value) ? (int) $value : $default;

        if ($limit < 1) {
            return $default;
        }

        return min($max, $limit);
    }

    private static function firstNestedError(mixed $errors): ?string
    {
        if (!is_array($errors)) {
            return null;
        }

        if (isset($errors['_errors'][0]['message'])) {
            return (string) $errors['_errors'][0]['message'];
        }

        foreach ($errors as $error) {
            $message = self::firstNestedError($error);
            if ($message !== null) {
                return $message;
            }
        }

        return null;
    }
}
