#!/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;

use Test::MockFile;

# 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 get_backup_jobs      { return ( { job_uuid => 'test-uuid', is_active => 1 } ); }
    sub set_current_run_uuid { return 1; }

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

    package Cpanel::Validate::UUID;

    sub is_valid_uuid {
        my ($uuid) = @_;
        return $uuid =~ /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i ? 1 : 0;
    }

    $INC{'Data/UUID.pm'} = 1;

    package Data::UUID;
    sub new        { return bless {}, shift; }
    sub create_str { return 'a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6'; }

    $INC{'POSIX.pm'} = 1;

    package POSIX;
    sub setsid { 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 'run_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::run_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 'run_backup_job - missing job_uuid' => 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( {} ) };
    my $metadata = {};

    my $response = Whostmgr::API::1::CometBackup::run_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';
    is $response->{started}, 0, 'Response indicates not started';

    return;
};

subtest 'run_backup_job - invalid UUID format' => 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 => 'not-a-uuid' } ) };
    my $metadata = {};

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

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/Invalid UUID format/i, 'Error mentions invalid UUID';

    return;
};

subtest 'run_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(
        'get_backup_jobs' => sub {
            return ();
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => 'a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6' } ) };
    my $metadata = {};

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

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/Backup job not found/i, 'Error mentions job not found';

    return;
};

subtest 'run_backup_job - job not active' => 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(
        'get_backup_jobs' => sub {
            return ( { job_uuid => 'a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6', is_active => 0 } );
        }
    );

    my $args     = { json => Cpanel::JSON::Dump( { job_uuid => 'a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6' } ) };
    my $metadata = {};

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

    is $metadata->{ok}, 0, 'Metadata is set to not ok';
    like $metadata->{error}, qr/not active/i, 'Error mentions job not active';

    return;
};

done_testing();
