#                                     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

# BEGIN Augment generated code block
package Cpanel::Plugins::Components::Rules::Filter;

use cPstrict;
use Cpanel::Plugins::Components::Rules::True ();
use Cpanel::Imports;

use Moo;

extends 'Cpanel::Plugins::Components::Rules::Base';

=head1 MODULE

C<Cpanel::Plugins::Components::Rules::Filter>

=head1 DESCRIPTION

Base class for filter-type rules that operate on nested rules. Filter rules
take a nested rule configuration and apply additional filtering logic to the
results. If no rule is passed, the rule defaults to 'true' to allow all servers
in the fleet to be part of the random lottery.

This class provides common functionality for all filter rules.

Filter rules are designed to work with complex nested rule structures including
AND, OR, and NOT operations, allowing for sophisticated server selection logic.

=head1 SYNOPSIS

This is a base class and should not be used directly. Instead, extend it to
create specific filter implementations:

  package Cpanel::Plugins::Components::Rules::MyFilter;
  use Moo;
  extends 'Cpanel::Plugins::Components::Rules::Filter';

  sub apply_filter ($self, $nested_result) {
      # Implement your filter logic here
      return $nested_result && $self->custom_filter_logic();
  }

=head1 CONFIGURATION

Filter rules expect a configuration structure with the following format:

  {
      "rule": { ... },         # The rule to evaluate first
      # Additional filter-specific parameters at the same level
  }

=cut

=head1 METHODS

=over

=item * is_allowed -- Evaluates the nested rule and applies the filter

Processes the nested rule first, then applies the filter logic if the nested
rule returns true. This allows filters to only operate on servers that already
match the base criteria.

    RETURNS
        0 - The nested rule failed or the filter rejected the server
        1 - Both the nested rule and filter logic succeeded

    ERRORS
        Dies if the nested rule configuration is invalid
        Dies if the filter configuration is missing or invalid

=back

=cut

around BUILDARGS => sub {
    my ( $orig, $class, @args ) = @_;

    # Handle no arguments - provide default config
    return { config => { rule => { true => 1 } } } if @args == 0;

    # Handle single hashref argument
    if ( @args == 1 && ref $args[0] eq 'HASH' ) {
        my $temp = { config => $args[0] };
        $temp->{config}{rule} //= { true => 1 };
        return $temp;
    }

    return $class->$orig(@args);
};

sub is_allowed ($self) {
    my $config = $self->config;

    # Validate configuration structure first
    unless ( ref $config eq 'HASH' && defined $config->{rule} ) {
        die "Filter configuration must be a hash and must include a rule.";
    }

    my $rule = $config->{rule};

    # First evaluate the rule
    my $result = $self->process_rule( 'and', $rule );

    # If rule reports the server is not allowed, short-circuit and return false
    return !!0 unless $result;

    # Apply the filter logic (implemented by subclasses)
    return $self->apply_filter( $config ) ? !!1 : !!0;
}

=head2 apply_filter

Abstract method that must be implemented by subclasses to provide the specific
filter logic.

    ARGUMENTS
        $config - The complete configuration hash containing filter-specific parameters

    RETURNS
        0 or 1 - Whether the filter accepts the current server

=cut

sub apply_filter ( $self, $config ) {
    die "apply_filter method must be implemented by subclass";
}

1;

# END Augment generated code block
