<?php

declare(strict_types=1);

namespace App\Framework\HttpClient\Curl\Exception;

use App\Framework\Exception\FrameworkException;

/**
 * Exception thrown by Curl\MultiHandle operations
 *
 * Provides context-rich error messages for cURL multi handle failures
 */
final class MultiHandleException extends FrameworkException
{
    /**
     * Multi handle initialization failed
     */
    public static function initializationFailed(): self
    {
        return self::simple(message: 'Failed to initialize cURL multi handle', code: 502);
    }

    /**
     * Adding handle to multi handle failed
     */
    public static function addHandleFailed(int $errorCode): self
    {
        return self::simple(
            message: "Failed to add handle to cURL multi handle",
            code: 502
        )->withData([
            'curl_multi_error_code' => $errorCode,
            'error_message' => self::getMultiErrorMessage($errorCode),
        ]);
    }

    /**
     * Removing handle from multi handle failed
     */
    public static function removeHandleFailed(int $errorCode): self
    {
        return self::simple(
            message: "Failed to remove handle from cURL multi handle",
            code: 502
        )->withData([
            'curl_multi_error_code' => $errorCode,
            'error_message' => self::getMultiErrorMessage($errorCode),
        ]);
    }

    /**
     * Multi handle execution failed
     */
    public static function executionFailed(int $errorCode): self
    {
        return self::simple(
            message: "cURL multi handle execution failed",
            code: 502
        )->withData([
            'curl_multi_error_code' => $errorCode,
            'error_message' => self::getMultiErrorMessage($errorCode),
        ]);
    }

    /**
     * Multi handle select operation failed
     */
    public static function selectFailed(): self
    {
        return self::simple(
            message: 'cURL multi handle select operation failed',
            code: 502
        )->withData([
            'error_code' => -1,
            'error_message' => 'Select failed or no file descriptors available',
        ]);
    }

    /**
     * Setting multi handle option failed
     */
    public static function setOptionFailed(int $option, mixed $value, int $errorCode): self
    {
        return self::simple(
            message: "Failed to set cURL multi option",
            code: 400
        )->withData([
            'option' => $option,
            'value' => $value,
            'curl_multi_error_code' => $errorCode,
            'error_message' => self::getMultiErrorMessage($errorCode),
        ]);
    }

    /**
     * Get human-readable error message for CURLM_* error code
     */
    private static function getMultiErrorMessage(int $errorCode): string
    {
        return match ($errorCode) {
            CURLM_OK => 'OK',
            CURLM_BAD_HANDLE => 'Bad multi handle',
            CURLM_BAD_EASY_HANDLE => 'Bad easy handle',
            CURLM_OUT_OF_MEMORY => 'Out of memory',
            CURLM_INTERNAL_ERROR => 'Internal error',
            CURLM_BAD_SOCKET => 'Bad socket',
            CURLM_UNKNOWN_OPTION => 'Unknown option',
            CURLM_ADDED_ALREADY => 'Handle already added',
            default => "Unknown error code: {$errorCode}",
        };
    }
}
