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

use Cpanel::Update::Config ();

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

my $tiers_obj;

=head1 MODULE

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

=head1 DESCRIPTION

Evaluates if the current server's tier matches the provided tiers.

This class is used in rules where the 'tiers' rule is included.

=head1 SYNOPSIS

Check if the server is in the RELEASE tier:

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

Check if the server's tier is one of the selected tiers:

  use Cpanel::Plugins::Components::Rules::Tiers;
  my $return = Cpanel::Plugins::Components::Rules::Tiers->new([qw/edge current release/])->is_allowed();

When you are using the declaritive JSON syntax:

  {
    "tiers": "release"
  }

or

  {
    "tiers": [ "edge", "current", "release" ]
  }

When you are using the declaritive YAML syntax:

    tiers: release

or

    tiers:
    - edge
    - current
    - release

When you are using yaml syntax:

  - tiers:
    - EDGE
    - CURRENT

=cut

=head1 METHODS

=over

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

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

    ERRORS
        Fails if no tier 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 $tiers_ref = $self->config;

    # Validate the config passed
    die "You must provide one or more tiers in the constructor."
      if !defined $tiers_ref || ref $tiers_ref ne 'ARRAY';

    my $active_tier = Cpanel::Update::Config::get_tier();

    foreach my $tier (@$tiers_ref) {

        # TODO: DUCKS-3060
        # handle cpanel versions check
        # handle_version($active_tier) if ( $active_tier =~ /\./ );

        if ( lc $tier eq lc $active_tier ) {
            return !!1;
        }
    }
    return !!0;
}

sub handle_version ($active_tier, $tier) {
    my @multiple_versions = _get_diff_versions($active_tier);
    my $expected_tier     = get_remote_version_for_tier( lc $tier ) // '';
    next if !$expected_tier;
    foreach my $version (@multiple_versions) {
        next if !$version;
        my $version_tier = $tiers_obj->get_remote_version_for_tier($version) // '';
        return !!1 if $expected_tier eq $version_tier;
    }

}
sub _get_diff_versions ($active_tier) {
    my ( $major, $minor, $patch, $rev ) = ( split /\./, $active_tier, 4 );
    my ( $maj_min, $maj_min_patch ) = ( '', '' );
    if ( $major && $minor ) {
        $maj_min       = "$major.$minor";
        $maj_min_patch = "$major.$minor.$patch" if defined $patch && $patch =~ /[0-9]/;
    }
    return ( $active_tier, $maj_min, $maj_min_patch );

}

sub get_remote_version_for_tier ($tier) {
    if ( !$tiers_obj ) {
        require Cpanel::Update::Tiers;
        $tiers_obj = Cpanel::Update::Tiers->new();
    }
    return $tiers_obj->get_remote_version_for_tier($tier);
}

1;
