#!/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
# Statistical distribution validation tests for Random
# Tests chi-square goodness of fit and multiple probability levels
# 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';

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

subtest 'Chi-square goodness of fit test' => sub {
    my $config = {
        rule        => { true => 1 },
        sample_size => 10000,           # 10% probability
        fleet_size  => 100000
    };

    my $total_tests          = 1000;
    my $true_count           = 0;
    my $expected_probability = 0.1;

    # Generate many independent samples
    for my $i ( 1 .. $total_tests ) {
        my $filter = Cpanel::Plugins::Components::Rules::Random->new($config);
        $true_count++ if $filter->is_allowed();
    }

    my $observed_probability = $true_count / $total_tests;
    my $expected_count       = $total_tests * $expected_probability;

    # Chi-square test: (observed - expected)² / expected
    my $chi_square = ( ( $true_count - $expected_count )**2 ) / $expected_count;

    # For 1 degree of freedom, critical value at 95% confidence is 3.841
    ok( $chi_square < 3.841, "Chi-square test passes: $chi_square < 3.841" );

    # Also check the probability is within reasonable bounds (±3 standard deviations)
    my $std_dev = sqrt( $expected_probability * ( 1 - $expected_probability ) / $total_tests );
    my $margin  = 3 * $std_dev;

    ok(
        abs( $observed_probability - $expected_probability ) < $margin,
        sprintf(
            "Observed probability %.3f within %.3f of expected %.3f",
            $observed_probability, $margin, $expected_probability
        )
    );

    note("Chi-square statistic: $chi_square");
    note("Observed: $true_count/$total_tests (${observed_probability})");
    note("Expected: $expected_count/$total_tests ($expected_probability)");
};

subtest 'Multiple probability levels validation' => sub {
    my @test_cases = (
        { sample_size => 1000,  fleet_size => 100000, expected => 0.01, name => '1% probability' },
        { sample_size => 5000,  fleet_size => 100000, expected => 0.05, name => '5% probability' },
        { sample_size => 25000, fleet_size => 100000, expected => 0.25, name => '25% probability' },
        { sample_size => 50000, fleet_size => 100000, expected => 0.50, name => '50% probability' },
    );

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

            my $total_tests = 500;
            my $true_count  = 0;

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

            my $observed = $true_count / $total_tests;
            my $std_dev  = sqrt( $case->{expected} * ( 1 - $case->{expected} ) / $total_tests );
            my $margin   = 2.5 * $std_dev;                                                         # 99% confidence interval

            ok(
                abs( $observed - $case->{expected} ) < $margin,
                sprintf(
                    "Sample size %d: observed %.3f within %.3f of expected %.3f",
                    $case->{sample_size}, $observed, $margin, $case->{expected}
                )
            );

            note("Observed: $true_count/$total_tests (${observed})");
            note( "Expected: " . ( $case->{expected} * $total_tests ) . "/$total_tests (" . $case->{expected} . ")" );
            note("Margin of error: ±$margin");
        };
    }
};

subtest 'Large sample statistical convergence' => sub {
    my $config = {
        rule        => { true => 1 },
        sample_size => 20000,           # 20% probability
        fleet_size  => 100000
    };

    my $expected_probability = 0.2;
    my @sample_sizes         = ( 100, 500, 1000, 2000 );

    for my $sample_size (@sample_sizes) {
        subtest "Convergence with $sample_size samples" => sub {
            my $true_count = 0;

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

            my $observed = $true_count / $sample_size;
            my $std_dev  = sqrt( $expected_probability * ( 1 - $expected_probability ) / $sample_size );
            my $margin   = 3 * $std_dev;                                                                   # 99.7% confidence (3σ)

            ok(
                abs( $observed - $expected_probability ) < $margin,
                sprintf(
                    "N=%d: observed %.3f within %.3f of expected %.3f",
                    $sample_size, $observed, $margin, $expected_probability
                )
            );

            note("Standard error decreases with sample size: ±$margin");
        };
    }
};

done_testing;
