#                                      Copyright 2024 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 Cpanel::UpdateGatherer::modules::MalwareDetection;

use Cpanel::UpdateGatherer::Std;

use Cpanel::FindBin ();
use Cpanel::JSON    ();

use constant HISTORY_RETURN_LIMIT => 500;
use constant IMUNIFY_AGENT_BIN    => 'imunify360-agent';

sub compile ( $self, $meta_data ) {
    if ( my $agent_bin = Cpanel::FindBin::findbin(IMUNIFY_AGENT_BIN) ) {
        $meta_data->{malware_detected} = {
            imunify => _get_imunify_history($agent_bin),
        };
    }
    return 1;
}

sub _get_imunify_history ($agent_bin) {
    my $history_ar = _get_daily_history_from_agent($agent_bin);

    my $infected_file_count = scalar grep { $_->{resource_type} eq 'file' } @$history_ar;
    my $infected_db_count   = scalar grep { $_->{resource_type} eq 'db' } @$history_ar;

    return {
        'infected_files' => $infected_file_count,
        'infected_dbs'   => $infected_db_count,
    };
}

sub _get_daily_history_from_agent ($agent_bin) {
    my $count = 0;
    my $end   = 0;

    my $history_ar = [];

    my $last_checked = _one_day_ago();
    {
        my $first_page = _get_history_page( $agent_bin, $count, HISTORY_RETURN_LIMIT(), $last_checked ) or die "Unable to get malware history from Imunify!";
        $end = $first_page->{max_count};
        my $current_page_size = scalar @{ $first_page->{items} };
        push @$history_ar, _get_found_events_from_imunify_history_page( $first_page->{items} );
        $count += $current_page_size;
    }

    while ( $count < $end ) {
        my $next_page         = _get_history_page( $agent_bin, $count, HISTORY_RETURN_LIMIT(), $last_checked ) || last;
        my $current_page_size = scalar @{ $next_page->{items} };
        push @$history_ar, _get_found_events_from_imunify_history_page( $next_page->{items} );
        $count += $current_page_size;
    }

    return $history_ar;
}

sub _get_found_events_from_imunify_history_page ($events_ar) {
    return map {
        { %{$_}{ 'resource_type', 'event', 'id' } }
    } grep { $_->{event} eq 'found' } @$events_ar;
}

sub _get_history_page ( $agent_bin, $offset, $limit, $last_checked ) {
    my $cmd = _get_cmd( $agent_bin, $limit, $offset, $last_checked );

    my $output = _run_cmd($cmd);

    return Cpanel::JSON::Load($output);
}

sub _get_cmd ( $agent_bin, $limit, $offset, $last_checked ) {
    my $offset_arg = '';
    my $since_arg  = '';
    if ( $offset > 0 ) {
        $offset_arg = "--offset=$offset";
    }

    if ($last_checked) {
        $since_arg = "--since=$last_checked";
    }

    return qq{$agent_bin malware history list --json --limit=$limit $offset_arg $since_arg 2> /dev/null};
}

sub _one_day_ago {
    require Time::Piece;
    my $now = Time::Piece->new();
    return $now->epoch() - 24 * 60 * 60;
}

# this is a sub for testing
sub _run_cmd ($cmd) {
    return `$cmd`;
}

1;
