#include "Sim/Simulation/SpecularSimulation.h"
#include "Base/Axis/MakeScale.h"
#include "Base/Axis/Scale.h"
#include "Base/Const/Units.h"
#include "Device/Beam/Beam.h"
#include "Device/Data/Datafield.h"
#include "Device/Detector/IDetector.h"
#include "Device/Histo/SimulationResult.h"
#include "Param/Distrib/Distributions.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sample/Multilayer/Layer.h"
#include "Sample/Multilayer/MultiLayer.h"
#include "Sim/Background/ConstantBackground.h"
#include "Sim/Scan/AlphaScan.h"
#include "Sim/Scan/QzScan.h"
#include "Tests/GTestWrapper/google_test.h"
#include <iostream>
#include <numbers>

using std::numbers::pi;

class SpecularSimulationTest : public ::testing::Test {
protected:
    SpecularSimulationTest();

    std::unique_ptr<SpecularSimulation> defaultSimulation();

    MultiLayer sample;
};

SpecularSimulationTest::SpecularSimulationTest()
{
    Material mat0 = RefractiveMaterial("ambience", 0.0, 0.0);
    Material mat1 = RefractiveMaterial("PartA", 5e-6, 0.0);
    Material mat2 = RefractiveMaterial("substrate", 15e-6, 0.0);

    Layer layer0(mat0);
    Layer layer1(mat1, 10 * Units::nm);
    Layer layer2(mat2);

    sample.addLayer(layer0);
    sample.addLayer(layer1);
    sample.addLayer(layer2);
}

std::unique_ptr<SpecularSimulation> SpecularSimulationTest::defaultSimulation()
{
    AlphaScan scan(EquiDivision("axis", 10, 0.0 * Units::deg, 2.0 * Units::deg));
    scan.setWavelength(1.0);
    return std::make_unique<SpecularSimulation>(scan, sample);
}

TEST_F(SpecularSimulationTest, ConstructSimulation)
{
    auto sim = defaultSimulation();

    EXPECT_EQ(3u, sim->sample()->numberOfLayers());

    const SimulationResult sim_result = sim->simulate();

    EXPECT_EQ(sim_result.size(), 10u);
    EXPECT_EQ(sim_result.rank(), 1u);

    EXPECT_NEAR(0.1 * Units::deg, sim_result.convertedBinCenters(Coords::RADIANS).front(),
                Units::deg * 1e-11);
    EXPECT_NEAR(1.9 * Units::deg, sim_result.convertedBinCenters(Coords::RADIANS).back(),
                Units::deg * 1e-10);
}
