#!/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

# BEGIN Augment generated code block
# Fleet simulation validation tests for Random
# Tests cross-server consistency and distributed algorithm approximation
# END Augment generated code block

use cPstrict;

use Test2::V0;
use Test2::Tools::Explain;
use Test2::Plugin::NoWarnings;
use Test2::Tools::Subtest;
use Test2::Tools::Exception;

use Test::MockModule qw/strict/;

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

# Mock the True rule for testing
{

    package Cpanel::Plugins::Components::Rules::True;
    use Moo;
    extends 'Cpanel::Plugins::Components::Rules::Base';
    sub is_allowed { return !!1; }
}

$INC{'Cpanel/Plugins/Components/Rules/True.pm'} = 'inline';

use Cpanel::Plugins::Components::Rules::Random;

subtest 'Fleet-wide distribution approximation' => sub {

    # Simulate multiple servers with same configuration
    my $config = {
        rule        => { true => 1 },
        sample_size => 10000,
        fleet_size  => 100000           # Target 10% selection
    };

    my $simulated_servers = 1000;       # Simulate 1000 servers
    my $selected_servers  = 0;

    # Each "server" makes independent decision
    for my $server ( 1 .. $simulated_servers ) {
        my $filter = Cpanel::Plugins::Components::Rules::Random->new($config);
        $selected_servers++ if $filter->is_allowed();
    }

    my $actual_percentage   = ( $selected_servers / $simulated_servers ) * 100;
    my $expected_percentage = 10.0;

    # Allow ±3% variance for statistical fluctuation
    ok(
        abs( $actual_percentage - $expected_percentage ) < 3.0,
        sprintf(
            "Fleet simulation: %.1f%% selected (expected ~%.1f%%)",
            $actual_percentage, $expected_percentage
        )
    );

    note("Simulated $simulated_servers servers, $selected_servers selected ($actual_percentage%)");

    # Additional validation: check that we're within 2 standard deviations
    my $p              = 0.1;
    my $expected_count = $simulated_servers * $p;
    my $variance       = $simulated_servers * $p * ( 1 - $p );
    my $std_dev        = sqrt($variance);

    ok(
        abs( $selected_servers - $expected_count ) < 2 * $std_dev,
        sprintf(
            "Selection count within 2σ: %d vs %.1f ± %.1f",
            $selected_servers, $expected_count, 2 * $std_dev
        )
    );
};

subtest 'Multiple fleet configurations' => sub {
    my @fleet_configs = (
        { sample_size => 5000,  fleet_size => 100000, expected_pct => 5.0,  name => '5% selection' },
        { sample_size => 15000, fleet_size => 100000, expected_pct => 15.0, name => '15% selection' },
        { sample_size => 25000, fleet_size => 100000, expected_pct => 25.0, name => '25% selection' },
        { sample_size => 50000, fleet_size => 100000, expected_pct => 50.0, name => '50% selection' },
    );

    for my $fleet_config (@fleet_configs) {
        subtest $fleet_config->{name} => sub {
            my $config = {
                rule        => { true => 1 },
                sample_size => $fleet_config->{sample_size},
                fleet_size  => $fleet_config->{fleet_size}
            };

            my $simulated_servers = 500;
            my $selected_servers  = 0;

            for my $server ( 1 .. $simulated_servers ) {
                my $filter = Cpanel::Plugins::Components::Rules::Random->new($config);
                $selected_servers++ if $filter->is_allowed();
            }

            my $actual_percentage   = ( $selected_servers / $simulated_servers ) * 100;
            my $expected_percentage = $fleet_config->{expected_pct};

            # Allow ±5% variance for smaller sample sizes
            ok(
                abs( $actual_percentage - $expected_percentage ) < 5.0,
                sprintf(
                    "Fleet %s: %.1f%% selected (expected ~%.1f%%)",
                    $fleet_config->{name}, $actual_percentage, $expected_percentage
                )
            );

            note("Selected: $selected_servers/$simulated_servers (${actual_percentage}%)");
        };
    }
};

subtest 'Scalability with different fleet sizes' => sub {
    my @scale_tests = (
        { sample_size => 100,   fleet_size => 1000,    servers => 200,  name => 'Small fleet (1K)' },
        { sample_size => 1000,  fleet_size => 10000,   servers => 500,  name => 'Medium fleet (10K)' },
        { sample_size => 10000, fleet_size => 100000,  servers => 1000, name => 'Large fleet (100K)' },
        { sample_size => 50000, fleet_size => 1000000, servers => 2000, name => 'Very large fleet (1M)' },
    );

    for my $scale_test (@scale_tests) {
        subtest $scale_test->{name} => sub {
            my $config = {
                rule        => { true => 1 },
                sample_size => $scale_test->{sample_size},
                fleet_size  => $scale_test->{fleet_size}
            };

            my $simulated_servers    = $scale_test->{servers};
            my $selected_servers     = 0;
            my $expected_probability = $scale_test->{sample_size} / $scale_test->{fleet_size};

            for my $server ( 1 .. $simulated_servers ) {
                my $filter = Cpanel::Plugins::Components::Rules::Random->new($config);
                $selected_servers++ if $filter->is_allowed();
            }

            my $actual_percentage   = ( $selected_servers / $simulated_servers ) * 100;
            my $expected_percentage = $expected_probability * 100;

            # Allow larger variance for smaller fleets due to higher relative error
            my $tolerance = $scale_test->{fleet_size} < 10000 ? 8.0 : 4.0;

            ok(
                abs( $actual_percentage - $expected_percentage ) < $tolerance,
                sprintf(
                    "Scale %s: %.1f%% selected (expected ~%.1f%%, tolerance ±%.1f%%)",
                    $scale_test->{name}, $actual_percentage, $expected_percentage, $tolerance
                )
            );

            note( "Fleet size: " . $scale_test->{fleet_size} );
            note( "Sample size: " . $scale_test->{sample_size} );
            note("Simulated servers: $simulated_servers");
            note("Selected: $selected_servers (${actual_percentage}%)");
            note( "Expected probability: " . sprintf( "%.2f%%", $expected_percentage ) );
        };
    }
};

subtest 'Cross-datacenter consistency simulation' => sub {

    # Simulate multiple datacenters with identical configuration
    my $config = {
        rule        => { true => 1 },
        sample_size => 20000,
        fleet_size  => 100000           # 20% target selection
    };

    my @datacenter_results;
    my $datacenters    = 10;
    my $servers_per_dc = 200;

    for my $dc ( 1 .. $datacenters ) {
        my $dc_selected = 0;

        for my $server ( 1 .. $servers_per_dc ) {
            my $filter = Cpanel::Plugins::Components::Rules::Random->new($config);
            $dc_selected++ if $filter->is_allowed();
        }

        my $dc_percentage = ( $dc_selected / $servers_per_dc ) * 100;
        push @datacenter_results, $dc_percentage;

        note("Datacenter $dc: $dc_selected/$servers_per_dc (${dc_percentage}%)");
    }

    # Calculate variance across datacenters
    my $sum_percentage = 0;
    $sum_percentage += $_ for @datacenter_results;
    my $mean_percentage = $sum_percentage / @datacenter_results;
    my $variance        = 0;

    for my $result (@datacenter_results) {
        $variance += ( $result - $mean_percentage )**2;
    }
    $variance /= @datacenter_results;
    my $std_dev = sqrt($variance);

    # All datacenters should be within reasonable range of each other
    my $max_result = ( sort { $b <=> $a } @datacenter_results )[0];
    my $min_result = ( sort { $a <=> $b } @datacenter_results )[0];
    my $range      = $max_result - $min_result;

    ok(
        $range < 15.0,    # No datacenter should differ by more than 15%
        sprintf(
            "Cross-datacenter consistency: range %.1f%% (max: %.1f%%, min: %.1f%%)",
            $range, $max_result, $min_result
        )
    );

    ok(
        abs( $mean_percentage - 20.0 ) < 3.0,
        sprintf( "Overall fleet average: %.1f%% (expected ~20.0%%)", $mean_percentage )
    );

    note("Mean across datacenters: ${mean_percentage}%");
    note("Standard deviation: ${std_dev}%");
    note("Range: ${range}%");
};

subtest 'Temporal consistency simulation' => sub {

    # Simulate the same fleet configuration over multiple time periods
    my $config = {
        rule        => { true => 1 },
        sample_size => 15000,
        fleet_size  => 100000           # 15% target selection
    };

    my @time_period_results;
    my $time_periods       = 20;
    my $servers_per_period = 100;

    for my $period ( 1 .. $time_periods ) {
        my $period_selected = 0;

        for my $server ( 1 .. $servers_per_period ) {
            my $filter = Cpanel::Plugins::Components::Rules::Random->new($config);
            $period_selected++ if $filter->is_allowed();
        }

        my $period_percentage = ( $period_selected / $servers_per_period ) * 100;
        push @time_period_results, $period_percentage;
    }

    # Check for temporal stability (no significant drift over time)
    my $first_half  = [ @time_period_results[ 0 .. 9 ] ];
    my $second_half = [ @time_period_results[ 10 .. 19 ] ];

    my $first_sum = 0;
    $first_sum += $_ for @$first_half;
    my $first_mean = $first_sum / @$first_half;

    my $second_sum = 0;
    $second_sum += $_ for @$second_half;
    my $second_mean = $second_sum / @$second_half;

    ok(
        abs( $first_mean - $second_mean ) < 5.0,
        sprintf(
            "Temporal stability: first half %.1f%% vs second half %.1f%%",
            $first_mean, $second_mean
        )
    );

    # Overall mean should be close to expected
    my $overall_sum = 0;
    $overall_sum += $_ for @time_period_results;
    my $overall_mean = $overall_sum / @time_period_results;

    ok(
        abs( $overall_mean - 15.0 ) < 3.0,
        sprintf( "Temporal average: %.1f%% (expected ~15.0%%)", $overall_mean )
    );

    note("First 10 periods average: ${first_mean}%");
    note("Last 10 periods average: ${second_mean}%");
    note("Overall temporal average: ${overall_mean}%");
};

done_testing;
