<?php

declare(strict_types=1);

namespace App\Framework\HttpClient;

use App\Framework\Http\Headers;
use App\Framework\HttpClient\Curl\HandleOption;

final readonly class AuthenticationHandler
{
    public function configure(AuthConfig $auth, Headers $headers): AuthResult
    {
        return match ($auth->type) {
            AuthType::Basic => $this->setupBasicAuth($auth->credentials, $headers),
            AuthType::Bearer => $this->setupBearerAuth($auth->credentials, $headers),
            AuthType::OAuth2 => $this->setupOAuth2Auth($auth->credentials, $headers),
            AuthType::Digest => $this->setupDigestAuth($auth->credentials, $headers),
            AuthType::Custom => $this->setupCustomAuth($auth->credentials, $headers),
        };
    }

    private function setupBasicAuth(array $credentials, Headers $headers): AuthResult
    {
        $curlOptions = [];
        if (isset($credentials['username'], $credentials['password'])) {
            $curlOptions[HandleOption::UserPwd] = "{$credentials['username']}:{$credentials['password']}";
            $curlOptions[HandleOption::HttpAuth] = CURLAUTH_BASIC;
        }

        return new AuthResult($headers, $curlOptions);
    }

    private function setupBearerAuth(array $credentials, Headers $headers): AuthResult
    {
        if (isset($credentials['token'])) {
            $headers = $headers->with('Authorization', "Bearer {$credentials['token']}");
        }

        return new AuthResult($headers);
    }

    private function setupOAuth2Auth(array $credentials, Headers $headers): AuthResult
    {
        if (isset($credentials['token'])) {
            $headers = $headers->with('Authorization', "Bearer {$credentials['token']}");
        }

        return new AuthResult($headers);
    }

    private function setupDigestAuth(array $credentials, Headers $headers): AuthResult
    {
        $curlOptions = [];
        if (isset($credentials['username'], $credentials['password'])) {
            $curlOptions[HandleOption::UserPwd] = "{$credentials['username']}:{$credentials['password']}";
            $curlOptions[HandleOption::HttpAuth] = CURLAUTH_DIGEST;
        }

        return new AuthResult($headers, $curlOptions);
    }

    private function setupCustomAuth(array $credentials, Headers $headers): AuthResult
    {
        if (isset($credentials['headers']) && is_array($credentials['headers'])) {
            foreach ($credentials['headers'] as $name => $value) {
                $headers = $headers->with($name, $value);
            }
        }

        return new AuthResult($headers);
    }
}
