#                                     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::CompareVersion;
use cPstrict;

use Cpanel::Version;
use Cpanel::Version::Compare;

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

=head1 MODULE

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

=head1 DESCRIPTION

Evaluates if the current server has a specific cPanel Version.

This class is used if the config file has 'compare-version' listed.


=head1 SYNOPSIS

Check if the server has a cPanel version 110

  use Cpanel::Plugins::Components::Rules::CompareVersion;
  my $return = Cpanel::Plugins::Components::Rules::CompareVersion->new(
    operator => '=>',
    version => '11.126',
  )->is_allowed();

When you are using the declaritive JSON syntax:

  {
    "compareversion": {
        operator => "=>",
        version => "11.110"
    }
  }

=cut

=head1 CONSTRUCTOR

=head2 new

=head3 ARGUMENTS

=over

=item * operator

The operator to use for the comparison.

Must be one of: <, >, ==, !=, <=, >=

=item * version

The cPanel version to compare against.

=back

=cut

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

    # passing a hashref with args
    return { config => $args[0] }
      if @args == 1 && ref $args[0];

    # passing a hash of args with a config key including the hashref of args
    return $class->$orig(@args)
      if @args % 2 == 0 && $args[0] eq 'config' && ref $args[1] eq 'HASH';

    # passing a hash of args
    return { config => { @args } }
      if @args % 2 == 0;
};

=head1 METHODS

=over

=item * is_allowed -- Allow the campaign if rules are met.

    RETURNS
        0 - The cPanel version did not match the comparison.
        1 - The cPanel version matched the comnparison.

    ERRORS
        Fails if no operator is passed.
        Fails if no cPanel version is passed.
        Fails if unable to fetch the cPanel version.

=back

=cut

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

    # Validate the config passed
    my $version = $config->{version};
    die "You must provide one or more cPanel version."
      if !defined $version;

    # for now, we can restrict this in rules to specify the exact
    # two part version
    if ( $version !~ /^(\d){2}\.(\d){3}$/ ) {
        die "You must provide a two part cPanel version like 'xx.xxx'";
    }

    my $operator = $config->{operator};
    die "You must provide an operator for the cPanel version comparison."
      if !defined $operator;

    die sprintf("You must provide a valid operator for the cPanel version comparison: %s", join(', ', qw(== != < <= > >=) ) )
      if $operator !~ /^(==|!=|<|<=|>|>=)$/;

    my $current_version = Cpanel::Version::getversionnumber();
    if ( Cpanel::Version::Compare::compare_major_release( $current_version, $operator, $version ) ) {
        return !!1;
    }
    return !!0;
}

1;
