#!/usr/local/cpanel/3rdparty/bin/perl -w

#                                     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::example::app::Example1;

use cPstrict;
use Moo;

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

has '+markup' => (
    default => 'p2',
);

has '+priority' => (
    default => 2,
);

has '+slot' => (
    default => 'order',
);

package Cpanel::Plugins::Components::example::app::Example2;

use cPstrict;
use Moo;

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

has '+markup' => (
    default => 'p3',
);

has '+priority' => (
    default => 3,
);

has '+slot' => (
    default => 'order',
);

package Cpanel::Plugins::Components::example::app::Example3;

use cPstrict;
use Moo;

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

has '+markup' => (
    default => 'p1',
);

has '+priority' => (
    default => 1,
);

has '+slot' => (
    default => 'order',
);

package Cpanel::Plugins::Components::example::app::Example4;

use cPstrict;
use Moo;

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

has '+markup' => (
    default => 'p4',
);

has '+is_enabled' => (
    default => sub { \1 },
);

package Cpanel::Plugins::Components::example::app::Example5;

use cPstrict;
use Moo;

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

has '+markup' => (
    default => 'p5',
);

has '+is_enabled' => (
    default => sub { \0 },
);

package main;

use cPstrict;

use Test2::V0;
use Test2::Tools::Explain;
use Test2::Plugin::NoWarnings;
use Test2::Tools::Subtest;
use Test2::Tools::Exception;
use Test2::Tools::Compare qw/prop object call/;

use Test::MockModule qw/strict/;
use File::Temp;
use File::Slurper;

use Test::Cpanel::Policy testing => 'Cpanel::Plugins::Components';

use Cpanel::Plugins::Components ();

my $temp_dir = File::Temp->newdir();
mkdir $temp_dir . "/usr";
mkdir $temp_dir . "/usr/local";
mkdir $temp_dir . "/usr/local/cpanel";
mkdir $temp_dir . "/usr/local/cpanel/Cpanel";
mkdir $temp_dir . "/usr/local/cpanel/Cpanel/Plugins";
mkdir $temp_dir . "/usr/local/cpanel/Cpanel/Plugins/Components";
$Cpanel::Plugins::Components::LOAD_BASE       = "$temp_dir/usr/local/cpanel";
$Cpanel::Plugins::Components::COMPONENTS_PATH = "$temp_dir/usr/local/cpanel/Cpanel/Plugins/Components";

subtest 'Test priority sort' => sub {
    my $mock_loader = Test::MockModule->new('Cpanel::PluginManager');
    $mock_loader->redefine(
        new                => sub ( $class, @other ) { bless {}, $class },
        load_all_plugins   => sub ($self) { },
        get_loaded_plugins => sub ($self) {
            return (
                Cpanel::Plugins::Components::example::app::Example1->new(),
                Cpanel::Plugins::Components::example::app::Example2->new(),
                Cpanel::Plugins::Components::example::app::Example3->new(),
            );
        }
    );

    my $components = Cpanel::Plugins::Components::get_components( 'example', 'app' );
    is $components, {
        order => [
            object { call markup => 'p1'; },
            object { call markup => 'p2'; },
            object { call markup => 'p3'; },
        ]
      },
      "We got the expected components in their slots in the right order";
};

subtest 'Test filter disabled items' => sub {
    my $mock_loader = Test::MockModule->new('Cpanel::PluginManager');
    $mock_loader->redefine(
        new                => sub ( $class, @other ) { bless {}, $class },
        load_all_plugins   => sub ($self) { },
        get_loaded_plugins => sub ($self) {
            return (
                Cpanel::Plugins::Components::example::app::Example4->new(),
                Cpanel::Plugins::Components::example::app::Example5->new(),
            );
        }
    );

    my $components = Cpanel::Plugins::Components::get_components( 'example', 'app' );
    is $components, {
        default => [
            object { call markup => 'p4'; },
        ]
      },
      "We got the expected components in their slots in the right order";
};

subtest 'Test yaml loading' => sub {
    my $mock_loader = Test::MockModule->new('Cpanel::PluginManager');
    $mock_loader->redefine(
        new                => sub ( $class, @other ) { bless {}, $class },
        load_all_plugins   => sub ($self) { },
        get_loaded_plugins => sub ($self) {
            return ();
        }
    );

    mkdir $temp_dir . "/usr/local/cpanel/Cpanel/Plugins/Components/example";
    mkdir $temp_dir . "/usr/local/cpanel/Cpanel/Plugins/Components/example/app";
    my $yaml = <<~ "YAML";
        ---
        markup: welcome to the muppet show.
        YAML

    File::Slurper::write_text( "$Cpanel::Plugins::Components::COMPONENTS_PATH/example/app/muppets.yaml", $yaml );

    my $components = Cpanel::Plugins::Components::get_components( 'example', 'app' );
    is $components, {
        default => [
            object { call markup => 'welcome to the muppet show.'; },
        ]
      },
      "We got the expected components in their slots in the right order";

    unlink "$Cpanel::Plugins::Components::COMPONENTS_PATH/example/app/muppets.yaml";
};

subtest 'Test json loading' => sub {
    my $mock_loader = Test::MockModule->new('Cpanel::PluginManager');
    $mock_loader->redefine(
        new                => sub ( $class, @other ) { bless {}, $class },
        load_all_plugins   => sub ($self) { },
        get_loaded_plugins => sub ($self) {
            return ();
        }
    );

    mkdir $temp_dir . "/usr/local/cpanel/Cpanel/Plugins/Components/example";
    mkdir $temp_dir . "/usr/local/cpanel/Cpanel/Plugins/Components/example/app";
    my $json = <<~ "JSON";
        {
            "markup": "its inspirational..."
        }
        JSON

    File::Slurper::write_text( "$Cpanel::Plugins::Components::COMPONENTS_PATH/example/app/muppets.json", $json );

    my $components = Cpanel::Plugins::Components::get_components( 'example', 'app' );
    is $components, {
        default => [
            object { call markup => 'its inspirational...'; },
        ]
      },
      "We got the expected components in their slots in the right order";
};

done_testing;
