#pragma once

#include <array>
#include <string>
#include <string_view>
#include <vector>

#include <fesa/core/diagnostic.hpp>
#include <fesa/core/status.hpp>
#include <fesa/elements/beam/beam3d2.hpp>
#include <fesa/model/entity_origin.hpp>
#include <fesa/model/ids.hpp>

namespace fesa {

enum class FieldCoordinateSystem { global, element_local };

struct NodalFrame final {
    inline static constexpr FieldCoordinateSystem coordinate_system =
        FieldCoordinateSystem::global;
    inline static constexpr std::array<std::string_view, 6>
        displacement_components{
            "Ux", "Uy", "Uz", "Rx", "Ry", "Rz"};
    inline static constexpr std::array<std::string_view, 6>
        reaction_components{
            "RFx", "RFy", "RFz", "RMx", "RMy", "RMz"};

    std::vector<NodeId> node_ids;
    std::vector<EntityOrigin> origins;
    std::vector<std::array<double, 6>> displacement;
    std::vector<std::array<double, 6>> reaction;
};

struct BeamElementFrame final {
    inline static constexpr FieldCoordinateSystem coordinate_system =
        FieldCoordinateSystem::element_local;
    inline static constexpr std::array<std::string_view, 6>
        section_strain_components{
            "epsilon", "gamma_y", "gamma_z", "kappa_x", "kappa_y",
            "kappa_z"};
    inline static constexpr std::array<std::string_view, 6>
        section_force_components{
            "N", "Vy", "Vz", "T", "My", "Mz"};
    inline static constexpr std::string_view axial_stress_component =
        "sigma_xx";

    ElementId element;
    EntityOrigin origin;
    BeamFrame local_frame;
    std::array<BeamSectionResult, 2> end_results;
};

struct ElementFrame final {
    std::vector<BeamElementFrame> beams;
};

struct ResultFrame final {
    double step_time;
    NodalFrame nodal;
    ElementFrame element;
    std::vector<Diagnostic> diagnostics;
};

struct ResultStep final {
    std::string name;
    std::vector<ResultFrame> frames;
};

struct ResultDatabase final {
    std::string schema_version;
    std::vector<ResultStep> steps;
};

[[nodiscard]] Status validate_result_database(
    const ResultDatabase& database);

}  // namespace fesa
