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

#                                      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.

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

use Test2::V0;
use Test2::Tools::Explain;
use Test2::Tools::Compare;
use Test2::Tools::Exception;

use Test::MockModule;
use Test::MockFile;
use Cpanel::JSON;

# Pre-load stub modules to prevent dependencies from failing
BEGIN {
    $INC{'Cpanel/Plugins/Components/Rules.pm'}             = 1;
    $INC{'Cpanel/Plugins/Components/Rules/Util/NVData.pm'} = 1;
    $INC{'Cpanel/Plugins/Components/Rules/CompanyId.pm'}   = 1;

    # Pre-load Cpanel modules
    $INC{'Cpanel/Server/Type.pm'} = 1;

    package Cpanel::Server::Type;
    sub get_products { return { 'cometbackup' => 1 }; }

    $INC{'Cpanel/PwCache.pm'} = 1;

    package Cpanel::PwCache;
    sub new { return bless {}, shift; }

    $INC{'Cpanel/Config/Users.pm'} = 1;

    package Cpanel::Config::Users;
    sub getcpusers { return qw(user1 user2); }

    # Pre-load CometBackup modules with stubs that can be overridden
    $INC{'Whostmgr/CometBackup/Setup.pm'} = 1;

    package Whostmgr::CometBackup::Setup;
    our @EXPORT = qw(is_comet_agent_installed is_agent_logged_in setup_comet_agent install_comet_agent);
    sub is_comet_agent_installed { return 0; }
    sub is_agent_logged_in       { return 0; }
    sub setup_comet_agent        { return 1; }
    sub install_comet_agent      { return 1; }

    $INC{'Whostmgr/CometBackup/AgentManager.pm'} = 1;

    package Whostmgr::CometBackup::AgentManager;
    our @EXPORT = qw(get_status start);
    sub get_status { return ( 1, 'active' ); }
    sub start      { return ( 1, '' ); }

    $INC{'Whostmgr/CometBackup/CometBackupAPI.pm'} = 1;

    package Whostmgr::CometBackup::CometBackupAPI;
    our @EXPORT = qw(get_server_config);
    sub get_server_config { return {}; }

    $INC{'Whostmgr/CometBackup/BackupRunLogs.pm'} = 1;

    package Whostmgr::CometBackup::BackupRunLogs;
    sub new             { return bless {}, shift; }
    sub get_recent_runs { return (); }

    $INC{'Whostmgr/CometBackup/BackupJobs.pm'} = 1;

    package Whostmgr::CometBackup::BackupJobs;
    sub new               { return bless {}, shift; }
    sub enable_backup_job { return 1; }
}

# Mock the Constants module BEFORE importing CometBackup
BEGIN {
    $INC{'Whostmgr/CometBackup/Constants.pm'} = 1;

    package Whostmgr::CometBackup::Constants;
    our $DISABLED_TOUCHFILE = '/var/cpanel/comet/comet_backup_disabled';
    our $BACKUP_RUNNER_PATH = '/usr/local/cpanel/backup-runner.pl';
    our $RUN_LOG_DB         = '/var/cpanel/comet/backup_run_logs.db';
    1;
}

use Whostmgr::API::1::CometBackup ();

# Mock the logger globally to prevent file access
my $mock_logger_global = Test::MockModule->new('Cpanel::Logger');
$mock_logger_global->redefine(
    'info'  => sub { return 1; },
    'error' => sub { return 1; },
    'warn'  => sub { return 1; },
    'debug' => sub { return 1; }
);

subtest 'enable_backup_job - missing JSON parameter' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $args     = {};
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/Missing required 'json'/i, 'Error mentions missing json';

    return;
};

subtest 'enable_backup_job - missing job_uuid parameter' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { other_field => 'value' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/job_uuid.*required/i, 'Error mentions job_uuid required';
    ok exists $response->{enabled}, 'Response has enabled key';

    return;
};

subtest 'enable_backup_job - job_uuid is empty string' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => '' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/job_uuid.*required/i, 'Error mentions job_uuid required';

    return;
};

subtest 'enable_backup_job - successful enabling' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_ok' => sub {
            my ($metadata) = @_;
            $metadata->{ok} = 1;
            return 1;
        },
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $mock_jobs = Test::MockModule->new('Whostmgr::CometBackup::BackupJobs');
    $mock_jobs->redefine(
        'enable_backup_job' => sub {
            my ( $self, $job_uuid ) = @_;
            return 1;
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => 'test-job-uuid' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $metadata->{ok}, 1, 'Metadata is set to ok';
    ok exists $response->{enabled}, 'Response has enabled key';
    is $response->{enabled}->{job_uuid}, 'test-job-uuid', 'Enabled job_uuid matches input';

    return;
};

subtest 'enable_backup_job - job not found' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $mock_jobs = Test::MockModule->new('Whostmgr::CometBackup::BackupJobs');
    $mock_jobs->redefine(
        'enable_backup_job' => sub {
            return 0;
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => 'nonexistent-uuid' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/not found or already enabled/i, 'Error mentions job not found';
    ok exists $response->{enabled}, 'Response has enabled key';

    return;
};

subtest 'enable_backup_job - BackupJobs throws exception' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $mock_jobs = Test::MockModule->new('Whostmgr::CometBackup::BackupJobs');
    $mock_jobs->redefine(
        'enable_backup_job' => sub {
            die "Database error occurred";
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => 'test-uuid' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/Failed to enable backup job/i, 'Error mentions enable failure';
    ok exists $response->{enabled}, 'Response has enabled key';

    return;
};

subtest 'enable_backup_job - passes correct UUID to BackupJobs' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_ok' => sub {
            my ($metadata) = @_;
            $metadata->{ok} = 1;
            return 1;
        },
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $passed_uuid;
    my $mock_jobs = Test::MockModule->new('Whostmgr::CometBackup::BackupJobs');
    $mock_jobs->redefine(
        'enable_backup_job' => sub {
            my ( $self, $job_uuid ) = @_;
            $passed_uuid = $job_uuid;
            return 1;
        }
    );

    my $test_uuid = 'my-custom-uuid-12345';
    my $args      = { json => Cpanel::JSON::Dump( { job_uuid => $test_uuid } ) };
    my $metadata  = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    is $passed_uuid,                     $test_uuid, 'Correct UUID passed to enable_backup_job method';
    is $response->{enabled}->{job_uuid}, $test_uuid, 'Response contains correct UUID';

    return;
};

subtest 'enable_backup_job - response structure on success' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_ok' => sub {
            my ($metadata) = @_;
            $metadata->{ok} = 1;
            return 1;
        },
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => 'uuid-789' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    ok ref $response eq 'HASH',                 'Response is a hash reference';
    ok exists $response->{enabled},             'Response has enabled key';
    ok ref $response->{enabled} eq 'HASH',      'enabled is a hash reference';
    ok exists $response->{enabled}->{job_uuid}, 'enabled contains job_uuid';

    return;
};

subtest 'enable_backup_job - response structure on error' => sub {
    my $mock_utils = Test::MockModule->new('Whostmgr::API::1::Utils');
    $mock_utils->redefine(
        'set_metadata_not_ok' => sub {
            my ( $metadata, $error ) = @_;
            $metadata->{ok}    = 0;
            $metadata->{error} = $error;
            return 1;
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => '' } ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::enable_backup_job( $args, $metadata );

    ok ref $response eq 'HASH',            'Response is a hash reference';
    ok exists $response->{enabled},        'Response has enabled key';
    ok ref $response->{enabled} eq 'HASH', 'enabled is a hash reference';
    is scalar( keys %{ $response->{enabled} } ), 0, 'enabled is empty hash on error';

    return;
};

done_testing();
