#pragma once

#include "fesa/core/status.hpp"
#include "fesa/math/matrix.hpp"
#include "fesa/math/vector.hpp"
#include "fesa/model/model_types.hpp"

#include <array>
#include <cstddef>
#include <string>
#include <vector>

namespace fesa {

struct ConstantLocalLineLoad {
    double px;
    double py;
    double pz;
    double mx;
};

struct BeamStressPoint {
    int gaussPoint;
    std::size_t sectionPoint;
    double x1;
    double x2;
    double s11;
    std::string source;
};

struct BeamRecovery {
    std::array<std::array<double, 6>, 2> equilibriumEndActions;
    std::array<std::array<double, 4>, 2> endpointSectionResultants;
    std::array<std::array<double, 4>, 2> gaussGeneralizedStrains;
    std::array<std::array<double, 4>, 2> gaussGeneralizedResultants;
    std::vector<BeamStressPoint> stressPoints;
};

// Implements the approved two-node straight prismatic B33 Euler-Bernoulli
// kernel. Equation numbering and element identity remain outside this type.
class EulerBeam3D {
public:
    static Result<EulerBeam3D> create(const Node& firstNode,
                                      const Node& secondNode,
                                      const GeneralBeamSection& section,
                                      const LinearElasticMaterial& material);
    Matrix localStiffness() const;
    Matrix globalStiffness() const;
    Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const;
    BeamRecovery recover(const Vector& globalElementDisplacement) const;

private:
    EulerBeam3D(double length,
                double youngsModulus,
                double shearModulus,
                double area,
                double iy,
                double iz,
                double torsionalConstant,
                std::array<double, 9> rotation,
                std::vector<std::array<double, 2>> sectionPoints);

    double length_;
    double youngsModulus_;
    double shearModulus_;
    double area_;
    double iy_;
    double iz_;
    double torsionalConstant_;
    std::array<double, 9> rotation_;
    std::vector<std::array<double, 2>> sectionPoints_;
};

} // namespace fesa
