#!/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
package Cpanel::Plugins::Components::Rules::True;
use cPstrict;
use Moo;
extends 'Cpanel::Plugins::Components::Rules::Base';

sub is_allowed ($self) {
    return !!1;
}

package Cpanel::Plugins::Components::Rules::False;
use cPstrict;
use Moo;
extends 'Cpanel::Plugins::Components::Rules::Base';

sub is_allowed ($self) {
    return !!0;
}

package main;

use cPstrict;

$INC{'/usr/local/cpanel/Cpanel/Plugins/Components/Rules/True.pm'}  = 'inline';
$INC{'/usr/local/cpanel/Cpanel/Plugins/Components/Rules/False.pm'} = 'inline';

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

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

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

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

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_obj   = Cpanel::Plugins::Components::Rules->new( config => $phrase, campaign_id => $campaign_id );

    is $rules_obj->{'campaign_id'}, $campaign_id, "Rules object is constructed with campaign_id";
    is $rules_obj->{'config'},      $phrase,      "Rules object is constructed with config";
};

subtest 'Verify Rules process from JSON' => sub {
    my @mocks;
    my $json_array_true = '["true",1]';
    push @mocks, Test::MockFile->file( "Cpanel/Plugins/Components/Rules/true_array.json", $json_array_true );

    my $json_array_false = '["false",1]';
    push @mocks, Test::MockFile->file( "Cpanel/Plugins/Components/Rules/false_array.json", $json_array_false );

    my $json_object_true = '{"true":1}';
    push @mocks, Test::MockFile->file( "Cpanel/Plugins/Components/Rules/true_object.json", $json_object_true );

    my $json_object_false = '{"false":1}';
    push @mocks, Test::MockFile->file( "Cpanel/Plugins/Components/Rules/false_object.json", $json_object_false );

    my $got = Cpanel::Plugins::Components::Rules->new( config_file => 'Cpanel/Plugins/Components/Rules/true_array.json' )->is_allowed();
    is $got, !!1, "Evaluation of JSON Array returned true value as expected.";

    $got = Cpanel::Plugins::Components::Rules->new( config_file => 'Cpanel/Plugins/Components/Rules/false_array.json' )->is_allowed();
    is $got, !!0, "Evaluation of JSON Array returned false value as expected.";

    $got = Cpanel::Plugins::Components::Rules->new( config_file => 'Cpanel/Plugins/Components/Rules/true_object.json' )->is_allowed();
    is $got, !!1, "Evaluations of JSON Object returned true value as expected.";

    $got = Cpanel::Plugins::Components::Rules->new( config_file => 'Cpanel/Plugins/Components/Rules/false_object.json' )->is_allowed();
    is $got, !!0, "Evaluations of JSON Object returned false value as expected.";
};

subtest 'Verify Rules process from perl configuration HASH/ARRAY' => sub {
    my $got = Cpanel::Plugins::Components::Rules->new( config => [ "true" => 1 ] )->is_allowed();
    is $got, !!1, "Evaluation of JSON Array returned true value as expected.";

    $got = Cpanel::Plugins::Components::Rules->new( config => [ "false" => 1 ] )->is_allowed();
    is $got, !!0, "Evaluation of JSON Array returned false value as expected.";

    $got = Cpanel::Plugins::Components::Rules->new( config => { "true" => 1 } )->is_allowed();
    is $got, !!1, "Evaluations of JSON Object returned true value as expected.";

    $got = Cpanel::Plugins::Components::Rules->new( config => { "false" => 1 } )->is_allowed();
    is $got , !!0, "Evaluations of JSON Object returned false value as expected.";
};

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

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

    my $first_check = [
        'feature-flag' => 'cpanel-360Monitoring-prerelease-disabled',
        'feature-flag' => 'cpanel-360Monitoring-disabled',
        'date-range'   => {
            'start_date' => '05-06-1987',
            'end_date'   => '07-15-2024'
        },
    ];

    my $second_check = [
        'or' => [
            'feature-flag' => 'cpanel-360Monitoring-enabled',
            'company-id'   => [ 17, 256 ],
        ]
    ];

    my $custom_filter = [
        'not' => [
            'feature-flag' => 'cpanel-360Monitoring-prerelease-disabled',
            'feature-flag' => 'cpanel-360Monitoring-disabled',
            'date-range'   => {
                'start_date' => '05-06-1987',
                'end_date'   => '07-15-2024'
            },
        ],
        'or' => [
            'feature-flag' => 'cpanel-360Monitoring-enabled',
            'company-id'   => [ 17, 256 ],
        ],
    ];

    my $got = Cpanel::Plugins::Components::Rules->new( config => $first_check )->is_allowed();
    is $got, !!0, "Evaluations of first check returns false.";

    $got = Cpanel::Plugins::Components::Rules->new( config => $second_check )->is_allowed();
    is $got, !!0, "Evaluations of second check returns false.";

    $got = Cpanel::Plugins::Components::Rules->new( config => $custom_filter )->is_allowed();
    is $got, !!0, "Evaluations of complex object returns false.";
};

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

    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',
            ]
        ]
    ];

    $mock_cid->redefine(
        get_company_id => sub {
            return 7;
        }
    );
    my $got = Cpanel::Plugins::Components::Rules->new( config => $check_or )->is_allowed();
    is $got, !!1, "Evaluations of check returns true if companyid is 7. (from second hash phrase)";

    $mock_cid->redefine(
        get_company_id => sub {
            return 14;
        }
    );
    $got = Cpanel::Plugins::Components::Rules->new( config => $check_or )->is_allowed();
    is $got, !!0, "Evaluations of check returns false if companyid is 14. (matches none of the phrases)";

    $mock_cid->redefine(
        get_company_id => sub {
            return 17;
        }
    );
    $got = Cpanel::Plugins::Components::Rules->new( config => $check_or )->is_allowed();
    is $got, !!1, "Evaluations of check returns true if companyid is 17. (matches final array phrase)";
};

subtest 'Verify nested rules and' => 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" => [
                    7,
                    256
                ],
                'feature-flag' => 'cpanel-360Monitoring-prerelease-disabled',
            },
            [       # a`` anb b``
                'feature-flag',
                'cpanel-360Monitoring-disabled',
            ]
        ]
    ];

    $mock_cid->redefine(
        get_company_id => sub {
            return 7;
        }
    );
    my $got = Cpanel::Plugins::Components::Rules->new( config => $check_and )->is_allowed();
    is $got, !!1, "Evaluations of check returns true if companyid is 7 and all the other.";

    $mock_cid->redefine(
        get_company_id => sub {
            return 14;
        }
    );
    $got = Cpanel::Plugins::Components::Rules->new( config => $check_and )->is_allowed();
    is $got, !!0, "Evaluations of check returns false if companyid is 14.";

    $mock_cid->redefine(
        get_company_id => sub {
            return 7;
        }
    );
    $mock->redefine(
        is_feature_enabled => sub ($flag) {
            $flag eq 'cpanel-360Monitoring-prerelease-disabled' ? 1 : 0;
        }
    );
    $got = Cpanel::Plugins::Components::Rules->new( config => $check_and )->is_allowed();
    is $got, !!0, "Evaluations of check returns false but because the second clause is false";
};

subtest 'Verify nested rules not with list' => sub {

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

    $mock_cid->redefine(
        get_company_id => sub {
            return 7;
        }
    );
    my $got = Cpanel::Plugins::Components::Rules->new( config => $check_not )->is_allowed();
    is $got, !!0, "Evaluations of check returns false if companyid is 7.";

    $mock_cid->redefine(
        get_company_id => sub {
            return 8;
        }
    );
    $got = Cpanel::Plugins::Components::Rules->new( config => $check_not )->is_allowed();
    is $got, !!0, "Evaluations of check returns false if companyid is 8.";

    $mock_cid->redefine(
        get_company_id => sub {
            return 9;
        }
    );
    $got = Cpanel::Plugins::Components::Rules->new( config => $check_not )->is_allowed();
    is $got, !!1, "Evaluations of check returns true if companyid is 9.";

};

done_testing;
