#include "Runner.h"
#include <algorithm>
#include <random>

namespace deeppluck::benchmark
{
juce::var evaluatePairs (const juce::var& input)
{
    const auto pairs=input["pairs"];
    require(pairs.isArray() && pairs.size()==9,"Statistics require exactly nine paired repetitions");
    std::array<double,9> improvement{},regression{};
    for(int i=0;i<9;++i)
    {
        require(pairs[i].hasProperty("baseline_rtf") && pairs[i].hasProperty("candidate_rtf"),"Missing paired RTF");
        const auto s=static_cast<double>(pairs[i]["baseline_rtf"]),c=static_cast<double>(pairs[i]["candidate_rtf"]);
        require(std::isfinite(s)&&std::isfinite(c)&&s>0&&c>0,"Invalid RTF in statistics");
        improvement[static_cast<size_t>(i)]=100*(s-c)/s;
        regression[static_cast<size_t>(i)]=-improvement[static_cast<size_t>(i)];
    }
    const auto statistics=[](std::array<double,9> values)
    {
        auto sorted=values; std::sort(sorted.begin(),sorted.end());
        std::array<double,9> deviations{};
        for(size_t i=0;i<values.size();++i) deviations[i]=std::abs(values[i]-sorted[4]);
        std::sort(deviations.begin(),deviations.end());
        std::mt19937 generator(0xD0115001u);
        std::vector<double> medians(10000);
        for(auto& median:medians)
        {
            std::array<double,9> draw{};
            for(auto& sample:draw)
            {
                std::uint32_t next=0;
                do {next=static_cast<std::uint32_t>(generator());} while(next>=4294967292u);
                sample=values[next%9u];
            }
            std::sort(draw.begin(),draw.end()); median=draw[4];
        }
        std::sort(medians.begin(),medians.end());
        auto out=object(); put(out,"median_percent",sorted[4]); put(out,"minimum_percent",sorted.front());
        put(out,"maximum_percent",sorted.back()); put(out,"mad_percent",deviations[4]);
        put(out,"ci95_lower_percent",medians[249]); put(out,"ci95_upper_percent",medians[9750]);
        put(out,"all_pair_percentages",array(values)); return out;
    };
    auto out=object(); const auto gain=statistics(improvement),loss=statistics(regression);
    put(out,"improvement",gain); put(out,"regression",loss);
    put(out,"seed","0xD0115001"); put(out,"engine","std::mt19937"); put(out,"resamples",10000);
    put(out,"lower_index",249); put(out,"upper_index",9750); put(out,"rejection_limit",static_cast<juce::int64>(4294967292LL));
    put(out,"efficiency_threshold_pass",static_cast<double>(gain["median_percent"])>=5 && static_cast<double>(gain["ci95_lower_percent"])>0);
    put(out,"confirmed_regression",static_cast<double>(loss["median_percent"])>3 && static_cast<double>(loss["ci95_lower_percent"])>0);
    put(out,"full_milestone_pass",false); return out;
}
}
