#                                     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::Util::Normalize;

use cPstrict;
use Cpanel::Imports;

=head1 MODULE

C<Cpanel::Plugins::Components::Rules::Util::Normalize>

=head1 DESCRIPTION

Convert hash refs into array refs, recursively, to keep data sorted.

=head1 SYNOPSIS

  use Cpanel::Plugins::Components::Rules::Util::Normalize ();
  Cpanel::Plugins::Components::Rules::Util::Normalize::normalize($config);

=head1 METHODS

=over

=item * normalize -- Recursively convert hash refs into array refs

    ARGUMENT
        config - The set of rules. First example has an 'or' rule needing conversion.
        Second example is skipped.

            $config = [
                'not',
                [
                    'feature-flag',
                    'cpanel-360Monitoring-prerelease-disabled',
                ],
                'or',
                {
                    feature-flag => 'cpanel-360Monitoring-enabled',
                    company-id => [
                        7,
                        265
                    ]
                }
            ];

            $config = [
                'personalization',
                {
                    'name'     => 'homepage-app-enabled',
                    ...
                },
                'company-id',
                [
                    7,
                    2869
                ]
            ];

    RETURNS
        $config -- The ruleset data structure, with all rules as arrayrefs.

=back

=cut

sub normalize ($config) {
    if ( !$config ) {
        logger->warn("The campaign data is not valid and rules will not be processed.");
        return;
    }
    elsif ( ref $config eq 'HASH' ) {

        # Converts hash data ref in to sorted array ref.
        my %hash = $config->%*;
        $config = [ %hash{ sort keys %hash } ];
        return $config;
    }
    elsif ( ref $config eq 'ARRAY' ) {

        # Dig one level deeper and fix things up there.
        # This has side effect on things like DateRange that exected a hashref
        # but now gets an arrayref of key/value pairs.
        normalize_children($config);

        return $config;
    }

    return $config;
}

sub normalize_children ($config) {
    if ( ref $config eq 'ARRAY' ) {
        my $length = scalar @$config;
        my $start  = 0;
        while ( $start < $length ) {

            # The first element might be the rule name, or the rule itself, since
            # 'and' is the default rule name if it's not given.
            my ( $rule, $rule_arg ) = @$config[ $start, $start + 1 ];

            # There are other types of rules. Skip if the rule is any other type.
            if ( $rule !~ /^(and|or)$/i ) {
                $start += 2;
                next;
            }
            if ( ref $config->[$start] eq 'HASH' ) {
                my %h = $config->[$start]->%*;
                $config->[$start] = [ %h{ sort keys %h } ];
            }
            $start++;
        }
    }
}

1;
