#pragma once

#include "fesa/core/status.hpp"

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

namespace fesa::test {

enum class ComparisonQuantity {
    displacement,
    reaction,
    sectionResultant
};

struct CanonicalComparisonRow {
    std::string modelId;
    std::string stepName;
    std::size_t frameIndex;
    std::string instanceName;
    std::int64_t sourceNodeLabel;
    ComparisonQuantity quantity;
    std::string component;
    double value;
    std::string unitDimension;
    std::string coordinateSystem;
    std::string hdf5DatasetPath;
};

struct RowDecision {
    CanonicalComparisonRow fesa;
    CanonicalComparisonRow reference;
    double absoluteError;
    double tolerance;
    bool passed;
};

struct ComponentMetrics {
    ComparisonQuantity quantity;
    std::string component;
    double referenceScale;
    double maximumAbsoluteError;
    double maximumNormalizedError;
    double rmsError;
    double normError;
    std::size_t worstRow;
};

struct PhysicsEvidence {
    double freeResidualNorm;
    std::array<double, 3> appliedForce;
    std::array<double, 3> reactionForce;
    std::array<double, 3> appliedMomentAboutOrigin;
    std::array<double, 3> reactionMomentAboutOrigin;
    bool endpointConsistencyPassed;
};

struct ComparisonReport {
    std::vector<RowDecision> rows;
    std::vector<ComponentMetrics> metrics;
    PhysicsEvidence physicsEvidence;
    bool stressComparisonApplicable;
    std::string stressComparisonReason;
    bool passed;
};

// Test-only comparison support keeps Abaqus artifacts read-only and exposes no
// backend handles to the implementation or downstream verification Steps.
class ReferenceComparison {
public:
    static Result<ComparisonReport> compare(
        const std::filesystem::path& resultsHdf5,
        const std::filesystem::path& legacyReferenceDirectory);
    static Status writeDeterministicJson(
        const ComparisonReport& report,
        const std::filesystem::path& outputJson);
};

} // namespace fesa::test
