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

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

use v5.36;
use Test::More;
use Test::Exception;
use Test::Deep;
use File::Path qw(make_path);

use experimental 'builtin';

use Whostmgr::360Monitoring::Util ();
use Whostmgr::360Monitoring::Agent;

use constant INI_VALID => <<_INI_;
[DEFAULT]
max_data_span = 60
max_data_age = 600
logging_level = 30
threads = 100
interval = 60
_INI_

use constant INI_REFLOW => <<_INI_;
# --------------------------------------------------------
# Warning: DO NOT EDIT THIS FILE.
# --------------------------------------------------------
# Description: agent360.ini for cPanel & WHM server. This
# configuration file is generated automatically by the
# cpanel-monitoring-plugin and used in conjunction with
# the 360 Monitoring.
# --------------------------------------------------------
[DEFAULT]
interval=60

[agent]
interval=60
logging_level=30
max_data_age=600
max_data_span=60

[data]
interval=60

[execution]
interval=60
threads=100
_INI_

use constant INI_CORRUPT => <<_INI_;
[DEFAULT
max_data_span = 60
_INI_

throws_ok(
    sub { Whostmgr::360Monitoring::Agent::from_INI( \INI_CORRUPT ) },
    qr/Syntax error at line 1: '\[DEFAULT'/,
    "from_INI dies when ini file is malformed"
);

throws_ok(
    sub { Whostmgr::360Monitoring::Agent::from_INI("INVALID") },
    qr/must be a reference/,
    "from_INI dies when ini file is not a reference"
);

lives_ok(
    sub { Whostmgr::360Monitoring::Agent::from_INI( \INI_VALID ) },
    "from_INI lives when ini file is correct"
);

my $agent = Whostmgr::360Monitoring::Agent::from_INI( \INI_VALID );
is( $agent->to_INI, INI_REFLOW, "INI Reflows properly" );

## Let's ensure either way we construct the object we get the same result
subtest "Construct from reflow with ::from_INI" => sub {
    my $agent2 = Whostmgr::360Monitoring::Agent::from_INI( \INI_REFLOW );
    cmp_deeply( $agent->serialize, $agent2->serialize, "produces the same result [serialize test]" );
    is( $agent->to_INI, $agent2->to_INI, "produces the same result [to_INI test]" );
};

subtest "settings_agent->max_data_span" => sub {
    my $before = 60;
    my $after  = 42;
    is( $agent->settings_agent->max_data_span, $before, "value correct from INI" );
    $agent->settings_agent->max_data_span($after);
    is( $agent->settings_agent->max_data_span, $after, "correct after setter" );
    like( get_section( $agent->to_INI, 'agent' ), qr/max_data_span=42/s, "modification found in to_INI" );
    $agent->settings_agent->max_data_span(60);
};

subtest "settings_execution->threads" => sub {
    my $before = 100;
    my $after  = 42;
    is( $agent->settings_execution->threads, $before, "value correct from INI" );
    $agent->settings_execution->threads($after);
    is( $agent->settings_execution->threads, $after, "correct after setter" );
    like( get_section( $agent->to_INI, 'execution' ), qr/threads=$after/s, "modification found in to_INI" );
    $agent->settings_agent->max_data_span($before);
};

subtest "settings_data->interval" => sub {
    my $before = 60;
    my $after  = 42;
    is( $agent->settings_data->interval, $before, "value correct from INI" );
    $agent->settings_data->interval($after);
    is( $agent->settings_data->interval, $after, "correct after setter" );
    like( get_section( $agent->to_INI, 'data' ), qr/interval=$after/s, "modification found in to_INI" );
    $agent->settings_agent->max_data_span($before);
};

subtest "interval_source_locations" => sub {
    {
        my $ini = <<~"_INI_";
        [DEFAULT]
        interval=80

        [execution]
        interval=90

        [httpd]
        _INI_

        my $agent;
        lives_ok(
            sub { $agent = Whostmgr::360Monitoring::Agent::from_INI( \$ini ) },
            "from_INI"
        );
        is( $agent->get_plugin('httpd')->interval, 80, "sourced from default" );
    }

    {
        my $ini = <<~"_INI_";
        [httpd]
        _INI_

        my $agent;
        lives_ok(
            sub { $agent = Whostmgr::360Monitoring::Agent::from_INI( \$ini ) },
            "from_INI"
        );
        is( $agent->get_plugin('httpd')->interval, 60, "sourced from code if not present elsewhere" );
    }

    {
        my $ini = <<~"_INI_";
        [execution]
        interval=42

        [httpd]
        _INI_

        my $agent;
        lives_ok(
            sub { $agent = Whostmgr::360Monitoring::Agent::from_INI( \$ini ) },
            "from_INI"
        );
        is( $agent->settings_execution->interval,  42, "correct in settings_execution" );
        is( $agent->get_plugin('httpd')->interval, 42, "sourced from execution" );
    }

    {
        my $ini = <<~"_INI_";
        [execution]
        interval=42

        [httpd]
        interval=20
        _INI_

        my $agent;
        lives_ok(
            sub { $agent = Whostmgr::360Monitoring::Agent::from_INI( \$ini ) },
            "from_INI"
        );
        is( $agent->settings_execution->interval,  42, "correct in settings_execution" );
        is( $agent->get_plugin('httpd')->interval, 20, "sourced from plugin override" );
    }
};

subtest "Agent Errors" => sub {
    local $@;
    eval {
        my $agent = Whostmgr::360Monitoring::Agent->new();
        $agent->add_to_plugins( 'litespeed', {} );
    };
    like( $@, qr/litespeed/,                  "Module name present" );
    like( $@, qr/Missing required arguments/, "'Missing required arguments' present" );
};

sub get_section ( $ini, $section ) {
    return join "\n",
      grep /\[$section\]/,
      split /\n\n/s,
      $ini;
}

done_testing();

1;
