#pragma once

#include "fesa/core/status.hpp"

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

namespace fesa::test {

struct Mitc4ReferenceCase {
    std::string caseId;
    std::string expectedSourceElementType;
    std::filesystem::path inputPath;
    std::filesystem::path displacementCsvPath;
    std::filesystem::path resultsHdf5Path;
};

struct Mitc4RowDecision {
    std::string caseId;
    std::string instanceName;
    std::int64_t sourceNodeLabel;
    std::string component;
    double fesaValue;
    double referenceValue;
    double absoluteError;
    double tolerance;
    double normalizedError;
    bool blocking;
    bool withinTolerance;
};

struct Mitc4ComponentMetrics {
    std::string component;
    double referenceScale;
    double tolerance;
    double maximumAbsoluteError;
    double maximumNormalizedError;
    double rmsError;
    double vectorNormError;
    std::size_t worstRow;
};

struct Mitc4VectorMetrics {
    std::string instanceName;
    std::int64_t sourceNodeLabel;
    double displacementNormError;
    double rotationNormError;
};

struct Mitc4Warning {
    std::string code;
    std::size_t row;
    std::string message;
};

struct Mitc4ComparisonReport {
    std::string caseId;
    std::string sourceElementType;
    std::string internalFormulation;
    std::string integrationRule;
    std::vector<Mitc4RowDecision> rows;
    std::vector<Mitc4ComponentMetrics> metrics;
    std::vector<Mitc4VectorMetrics> vectorMetrics;
    std::vector<Mitc4Warning> warnings;
    std::size_t worstRow;
    bool passed;
};

class Mitc4ReferenceComparison {
public:
    static Result<Mitc4ComparisonReport> compare(
        const Mitc4ReferenceCase& referenceCase);
    static Status writeDeterministicJson(
        const Mitc4ComparisonReport& report,
        const std::filesystem::path& outputJson);
};

} // namespace fesa::test
