<?php

declare(strict_types=1);

namespace App\Framework\Exception\Core;

use App\Framework\Exception\ErrorCode;

/**
 * API error codes
 *
 * Covers API integration, external service communication, and response handling
 */
enum ApiErrorCode: string implements ErrorCode
{
    case REQUEST_FAILED = 'API001';
    case INVALID_RESPONSE = 'API002';
    case TIMEOUT = 'API003';
    case AUTHENTICATION_FAILED = 'API004';
    case SERVICE_UNAVAILABLE = 'API005';

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

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

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

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

            self::REQUEST_FAILED,
            self::TIMEOUT,
            self::AUTHENTICATION_FAILED => ErrorSeverity::ERROR,

            self::INVALID_RESPONSE => ErrorSeverity::WARNING,
        };
    }

    public function getDescription(): string
    {
        return match($this) {
            self::REQUEST_FAILED => 'API request execution failed',
            self::INVALID_RESPONSE => 'API response format is invalid',
            self::TIMEOUT => 'API request timed out',
            self::AUTHENTICATION_FAILED => 'API authentication failed',
            self::SERVICE_UNAVAILABLE => 'External API service is unavailable',
        };
    }

    public function getRecoveryHint(): string
    {
        return match($this) {
            self::REQUEST_FAILED => 'Check request parameters and network connectivity',
            self::INVALID_RESPONSE => 'Verify API version and response schema',
            self::TIMEOUT => 'Increase timeout or retry with exponential backoff',
            self::AUTHENTICATION_FAILED => 'Verify API credentials and permissions',
            self::SERVICE_UNAVAILABLE => 'Check service status or use fallback provider',
        };
    }

    public function isRecoverable(): bool
    {
        return true;
    }

    public function getRetryAfterSeconds(): ?int
    {
        return match($this) {
            self::TIMEOUT => 30,
            self::SERVICE_UNAVAILABLE => 60,
            default => null,
        };
    }
}
