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

use cPstrict;

use Test2::V0;
use Test2::Tools::Explain;
use Test2::Plugin::NoWarnings;
use Test2::Tools::Subtest;
use Test2::Tools::Exception;
use Test2::Tools::Ref;

use Test::MockModule qw/strict/;
use Test::MockFile   qw/strict/;

use Test::Cpanel::Policy testing => 'Cpanel::Plugins::Components::Rules';

use Cpanel::Plugins::Components::Rules::Base;

my $mock_cid = Test::MockModule->new("Cpanel::License::CompanyID");
$mock_cid->redefine(
    get_company_id => sub {
        1;
    }
);

subtest 'Verify ARGS on creation' => sub {
    my $phrase      = [ 'company-id', [ 1, 2, 3 ] ];
    my $campaign_id = 'example-campaign';

    my $rules_base = Cpanel::Plugins::Components::Rules::Base->new( config => $phrase, campaign_id => $campaign_id );
    is $rules_base->{'campaign_id'}, $campaign_id, "Base object 1 is constructed with campaign_id";
    is $rules_base->{'config'},      $phrase,      "Base object 1 is constructed with config";

    my $rules_base_2 = Cpanel::Plugins::Components::Rules::Base->new( config => $phrase );
    is $rules_base_2->{'campaign_id'}, undef,   "Base object 2 is constructed without campaign_id";
    is $rules_base_2->{'config'},      $phrase, "Base object 2 is constructed with config";
};

subtest 'Verify normalize' => sub {
    my $phrase   = { 'company-id' => [ 1, 2, 3 ] };
    my $base_obj = Cpanel::Plugins::Components::Rules::Base->new( config => $phrase );
    ref_ok( $base_obj->config,                         'HASH',  'config is a hash before normalize' );
    ref_ok( $base_obj->normalize( $base_obj->config ), 'ARRAY', 'config is an array after normalize' );
};

subtest 'Verify get_module_name' => sub {
    my $and = Cpanel::Plugins::Components::Rules::Base::get_module_name("and");
    my $not = Cpanel::Plugins::Components::Rules::Base::get_module_name("not");
    my $or  = Cpanel::Plugins::Components::Rules::Base::get_module_name("or");

    is $and, 'Cpanel::Plugins::Components::Rules::And', 'Module name for AND is retrieved';
    is $not, 'Cpanel::Plugins::Components::Rules::Not', 'Module name for NOT is retrieved';
    is $or,  'Cpanel::Plugins::Components::Rules::Or',  'Module name for OR is retrieved';
};

subtest 'Verify load_module' => sub {
    my @warnings;
    my $mock_logger = Test::MockModule->new('Cpanel::Logger');
    $mock_logger->redefine( 'warn', sub { shift @_; push @warnings, @_ } );

    my $phrase      = { 'company-id' => [ 1, 2, 3 ] };
    my $base_obj    = Cpanel::Plugins::Components::Rules::Base->new( config => $phrase );
    my $failed_load = $base_obj->load_module( 'Cpanel::Plugins::Components::Rules::DNE', $base_obj->config );

    like( $warnings[0], qr/Could not locate the rule module/, 'Expected warning captured' );

    my $loaded_module = $base_obj->load_module( 'Cpanel::Plugins::Components::Rules::And', $base_obj->config );
    is $loaded_module, 1, 'Module successfully loaded';
};

subtest 'Verify process_rule' => sub {
    my $mock = Test::MockModule->new('Cpanel::FeatureFlags');
    $mock->redefine( is_feature_enabled => sub { 1 } );

    my $check_and = [
        and => [    #( a` and b`) and (a`` and b``)
            {       # a` anb b`
                "company-id" => [
                    1,
                    7,
                    256
                ],
                'feature-flag' => 'cpanel-360Monitoring-prerelease-disabled',
            },
            [       # a`` anb b``
                'feature-flag',
                'cpanel-360Monitoring-disabled',
            ]
        ]
    ];

    my $check_or = [
        or => [    #( a` and b`) or (a`` and b``)
            {      # a` anb b`
                "company-id" => [
                    7,
                    256
                ],
                'feature-flag' => 'cpanel-360Monitoring-prerelease-disabled',
            },
            [      # a`` anb b``
                "company-id",
                [17],
                'feature-flag',
                'cpanel-360Monitoring-prerelease-disabled',
            ]
        ]
    ];

    my $check_not = [
        not => [    #!( a or b )  => !a and !b
            {
                "company-id" => 7,
            },
            [
                "company-id" => 8,
            ],
        ]
    ];

    my $base_and = Cpanel::Plugins::Components::Rules::Base->new( config => $check_and );
    my $base_not = Cpanel::Plugins::Components::Rules::Base->new( config => $check_not );
    my $base_or  = Cpanel::Plugins::Components::Rules::Base->new( config => $check_or );

    is $base_and->process_rule( $base_and->config, "" ), 1, 'AND rule is processed';
    is $base_not->process_rule( $base_and->config, "" ), 1, 'NOT rule is processed';
    is $base_or->process_rule( $base_and->config, "" ), 1, 'OR rule is processed';
};

done_testing;
