#!/usr/local/cpanel/3rdparty/bin/perl -w

#                                      Copyright 2025 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

package t::medium::Cpanel::Plugins::RestApiClient;

use cPstrict;
use Test::Cpanel::Policy;

use Test2::V0;
use Test2::Tools::Explain;
use Test2::Tools::Compare;
use Test2::Plugin::NoWarnings;
use Test2::Tools::Exception;
use Test::MockFile   qw/strict/;
use Test::MockModule;

use base qw(Test::Class);

use Cpanel::Plugins::RestApiClient ();

my ( $status, $success, $retries, $content, $headers );
my @mocks;
push( @mocks, Test::MockModule->new('Cpanel::HTTP::Client') );
$mocks[-1]->redefine( 'new'                  => sub { return bless {}, shift } );
$mocks[-1]->redefine( 'return_on_http_error' => sub { return shift; } );
$mocks[-1]->redefine(
    'request' => sub {
        my ( $self, $method, $path, $data ) = @_;
        $retries++;
        $headers = $data->{headers};
        return bless(
            {
                content => $content,
                status  => $status,
                success => $success,
            },
            "Cpanel::HTTP::Client::Response"
        );
    }
);

push( @mocks, Test::MockModule->new('Cpanel::Plugins::RestApiClient') );
$mocks[-1]->redefine( '_throw_error' => sub { die "An error was thrown." } );

push( @mocks, Test::MockModule->new('Cpanel::DIp::MainIP') );
$mocks[-1]->redefine( 'getmainserverip' => '1.2.3.4' );

my $mock_cpnat_file = Test::MockFile->file('/var/cpanel/cpnat', "1.2.3.4 11.12.13.14");

__PACKAGE__->new()->runtests() if !caller;

#----------------------------------------------------------------------

sub test_new : Tests(1) {

    my $obj = Cpanel::Plugins::RestApiClient->new();
    isa_ok( $obj, 'Cpanel::Plugins::RestApiClient' );

    return;
}

sub test_run : Tests(10) {

    my $obj = Cpanel::Plugins::RestApiClient->new();
    ok( dies { $obj->run() }, "Dies when the required attributes are not set." );

    $obj->base_url('https://foobar/v1');
    $obj->endpoint('users');
    $obj->main_ip(1);

    $status  = 200;
    $success = 1;
    ok( lives { $obj->run() }, "Lives when attribues are set, status is 200, and success is true when server has NATIP." );

    $mock_cpnat_file = '';
    $mock_cpnat_file = Test::MockFile->file('/var/cpanel/cpnat');
    ok( lives { $obj->run() }, "Lives when attribues are set, status is 200, and success is true when server does not have NATIP." );

    $retries = 0;
    $status  = 599;
    $success = 0;
    eval { $obj->run() };
    is( $retries, $obj->retry, "On network failure retry the request up to the value of retry." );

    $retries = 0;
    $status  = 505;
    $success = 0;
    eval { $obj->run() };
    is( $retries, 1, "Do not retry on an error that is not network related." );

    $status  = 200;
    $success = 1;
    $obj->main_ip(0);
    $content = '{"abcd":"efgh","foo":"bar"}';
    is( $obj->run(),                '{"abcd":"efgh","foo":"bar"}', "Got the expected content from a successful request." );
    is( $headers->{'Content-Type'}, 'application/json',            "The default Content-Type header is included." );

    $content = undef;
    is( $obj->run(), 1, "A true value is returned when the request is successful but returns no content." );

    $obj->auth_token('1234');
    $headers = undef;
    eval { $obj->run() };
    is( $headers->{'Authorization'}, 'Bearer 1234',      "The Authorization Bearer header is set when auth_token is defined." );
    is( $headers->{'Content-Type'},  'application/json', "The default Content-Type header is included also." );

    return;
}

1;
