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

use Cpanel::OS;

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

=head1 MODULE

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

=head1 DESCRIPTION

Evaluates if the current server's distribution matches the provided distribution.

This class is used if the campaign config file has 'distributions' listed.

C<Cpanel::Plugins::Components::Rules::Distributions> provides

=head1 SYNOPSIS

Check if the server belongs to cloudlinux distro:

  use Cpanel::Plugins::Components::Rules::Distributions;
  my $return = Cpanel::Plugins::Components::Rules::Distributions->new('cloudlinux')->is_allowed();

Check if the server's distro belongs to one of the select list of distros:

  use Cpanel::Plugins::Components::Rules::Distributions;
  my $return = Cpanel::Plugins::Components::Rules::Distributions->new(["centos-7", "cloudlinux", "almalinux-8.9"])->is_allowed();

When you are using the declaritive JSON syntax:

  {
    "distributions": centos-7.1
  }

or

  {
    "distributions": [ centos-7, ubuntu-22.04, cloudlinux-6.1 ]
  }

=cut

=head1 METHODS

=over

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

    RETURNS
        0 - The distribution check failed.
        1 - The distribution check succeeded.

    ERRORS
        Fails if no distribution data is passed.

=back

=cut

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

    # ( 1 )
    return { config => [ $args[0] ] }
      if @args == 1 && !ref $args[0];

    # ( [ 1 ] )
    return { config => $args[0] }
      if @args == 1 && ref $args[0];

    # ( config => 1 ) ... ( config => [1] )
    my %args = @args;
    $args{config} = [ $args{config} ] if !ref $args{config};
    return $class->$orig(%args);
};

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

    # Validate the config passed
    die "You must provide one or more distributions data."
      if !defined $distributions_ref || ref $distributions_ref ne 'ARRAY';

    foreach my $distribution (@$distributions_ref) {
        my ( $distro, $version ) = ( split /-/,  $distribution );
        my ( $major,  $minor )   = ( split /\./, $version ) if $version;

        my $os_distro = Cpanel::OS::distro();
        my $os_major  = Cpanel::OS::major();
        my $os_minor  = Cpanel::OS::minor();

        if ( $distro =~ /^$os_distro$/i ) {
            if ( $major && $major != $os_major ) {
                next;
            }
            if ( $minor && $minor != $os_minor ) {
                next;
            }
            return !!1;
        }
    }
    return !!0;

}

1;
