package Cpanel::API::Plugins;

#                                      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

use cPstrict;
use Cpanel::Imports;

use Cpanel::Plugins::UUID       ();
use Cpanel::Validate::Boolean   ();
use Cpanel::Plugins::Promotions ();

our %API = (
    get_uuid    => { allow_demo => 0 },
    reset_uuid  => { allow_demo => 0 },
    create_user => { allow_demo => 0 },
);

=head1 MODULE

C<Cpanel::API::Plugins>

=head1 DESCRIPTION

C<Cpanel::API::Plugins> provides methods to interface with the common plugin framework.

=head1 FUNCTIONS

=head2 get_uuid()

Get the user's plugin UUID.

=head3 ARGUMENTS

=over

None.

=back

=head3 RETURNS

The cPanel user's UUID shared across plugins.

=over

=item uuid - string

=back

=head3 EXAMPLES

CLI ( Arguments must be uri escaped ):

uapi --user=cpanel_user Plugins get_uuid

TT:

 [%
     SET result = execute( 'Plugins', 'get_uuid', );
     SET uuid = result.data.uuid;
 %]

=cut

sub get_uuid ( $args, $result ) {

    my $uuid = Cpanel::Plugins::UUID->new();
    $result->data( { uuid => $uuid->uuid } );

    return 1;
}

=head2 reset_uuid()

Reset the user's plugin UUID and optionally generate and return a new one.

=head3 ARGUMENTS

=over

None.

=back

=head3 RETURNS

The cPanel user's UUID shared across plugins.

=over

=item uuid - string

=back

=head3 EXAMPLES

CLI ( Arguments must be uri escaped ):

uapi --user=cpanel_user Plugins reset_uuid

TT:

 [%
     SET result = execute( 'Plugins', 'reset_uuid', );
     SET uuid = result.data.uuid;
 %]

=cut

sub reset_uuid ( $args, $result ) {

    my $uuid = Cpanel::Plugins::UUID->new();
    $result->data( { uuid => $uuid->reset() } );

    return 1;
}

=head2 can_show_promotions()

Determines if the server can show promotions for specific plugins.

=head3 ARGUMENTS

=over

C<plugin> -- String. The plugin we want to query.

=back

=head3 RETURNS

Whether or not this server can show promotions for a plugin.

=over

=item can_show_promotions - bool

=back

=cut

sub can_show_promotions ( $args, $result ) {

    my $plugin = $args->get_length_required('plugin');

    my $promotions = eval { Cpanel::Plugins::Promotions->new( { plugin => $plugin } ) };
    my $err        = $@ && $@->isa('Cpanel::Exception') ? $@->get_string() : $@;

    if ($err) {
        $result->error($err);
        $result->message("Could not load methods for plugin $plugin. Check $plugin for validity.");
        return;
    }

    $result->data( { can_show_promotions => $promotions->can_show_promotions() } );

    return 1;
}

=head2 create_user()

Implements the feature's own implementation of creating an user account
This creates a account for the provided extension's feature.

Fails if the extension has not implemented create_user method or if
there is no extension module created.

For ex: if the arguments provided is 'xovi'
This will call 'Cpanel::Xovi::User::create_user' and return the api_key



=head3 ARGUMENTS

=over

C<plugin> -- String. The feature/extension name

=back

=head3 RETURNS

The hash reference of service specific name/value pairs as returned by the cloud API

=over

=item create_user - hash_ref

=back

=cut

sub create_user ( $args, $result ) {

    my $feature = $args->get_length_required('plugin');

    # exclude internal Cpanel::Args arguments and plugin argument
    my @exclude_list = ( 'plugin', 'cpanel_jsonapi_apiversion', 'cpanel_jsonapi_func', 'cpanel_jsonapi_module', 'api.version' );

    my $exclude_str = join "|", @exclude_list;

    my @other_keys   = $args->get_keys_like(qr/^(?!.*\b$exclude_str\b).*/);
    my @other_values = $args->get(@other_keys);

    my %args;
    @args{@other_keys} = @other_values;

    # load the module
    my $module = 'Cpanel::' . ucfirst($feature) . '::User';

    _load_module($module);
    my $method     = 'create_user';
    my $method_ref = $module->can($method);
    die Cpanel::Exception::create( 'InvalidParameter', "$method not implemented on $module." ) if !$method_ref;
    return $result->data( $method_ref->( \%args ) );

}

sub _load_module ($module) {
    eval "require $module;";    ## no critic qw(BuiltinFunctions::ProhibitStringyEval)
    if ( my $exception = $@ ) {
        die Cpanel::Exception::create( 'InvalidParameter', "Could not locate the module '$module'. Perhaps the module does not currently support create_user $exception." );
    }

    return 1;
}
1;
