#include <numbers>

using std::numbers::pi;

#include "Sample/HardParticle/HardParticles.h"
#include "Tests/GTestWrapper/google_test.h"
#include "Tests/Unit/Numeric/MultiQTest.h"
#include <ff/Face.h> // for diagnostic

//! Check that form factors are invariant when q is transformed according to particle symmetry.

class FFSymmetryTest : public testing::Test {
protected:
    void run_test(IFormFactor* ff, std::function<C3(const C3&)> trafo, double eps, double qmag1,
                  double qmag2)
    {
        int failures = formfactorTest::run_test_for_many_q(
            [&](C3 q) -> complex_t { return ff->formfactor(q); },
            [&](C3 q) -> complex_t { return ff->formfactor(trafo(q)); }, qmag1, qmag2, eps);
        EXPECT_EQ(failures, 0);
    }
};

//*********** spheroids ***************

TEST_F(FFSymmetryTest, HemiEllipsoid)
{
    HemiEllipsoid ff(.53, .78, 1.3);
    run_test(
        &ff, [](const C3& q) -> C3 { return C3(-q.x(), q.y(), q.z()); }, 1e-12, 1e-99, 2e2);
    run_test(
        &ff, [](const C3& q) -> C3 { return C3(q.x(), -q.y(), q.z()); }, 1e-12, 1e-99, 2e2);
}

TEST_F(FFSymmetryTest, TruncatedSphere)
{
    TruncatedSphere ff(.79, .34, 0);
    run_test(
        &ff, [](const C3& q) -> C3 { return q.rotatedZ(pi / 3.13698); }, 8e-13, 1e-99, 2e2);
}

TEST_F(FFSymmetryTest, Spheroid)
{
    Spheroid ff(.73, .36);
    run_test(
        &ff, [](const C3& q) -> C3 { return q.rotatedZ(.123); }, 1e-12, 1e-99, 2e2);
}

// ****** TODO: tests that do not pass for the full q range *********
