#include <fesa/analysis/run_solver.hpp>

#include <optional>
#include <string>
#include <utility>

#include <fesa/io/abaqus/parser.hpp>
#include <fesa/io/abaqus/semantic_mapper.hpp>
#include <fesa/io/hdf5/writer.hpp>

namespace fesa {
namespace {

std::string path_utf8(const std::filesystem::path& path) {
    const std::u8string value = path.u8string();
    return {reinterpret_cast<const char*>(value.data()), value.size()};
}

}  // namespace

AnalysisRunResult run_solver(const AnalysisRequest& request) {
    ParseDeckResult parsed = parse_deck(request.input_path);
    if (!parsed.deck.has_value()) {
        return {false, std::nullopt, std::move(parsed.diagnostics)};
    }

    DomainBuildResult mapped = map_deck_to_domain(*parsed.deck);
    if (!mapped.domain.has_value()) {
        return {false, std::nullopt, std::move(mapped.diagnostics)};
    }

    const Hdf5InputIdentity identity{
        path_utf8(request.input_path),
        parsed.input_fingerprint,
    };

    AnalysisRunResult run = LinearStaticAnalysis{}.run(*mapped.domain);
    if (!run.succeeded || !run.results.has_value()) {
        return run;
    }

    std::vector<Diagnostic> write_diagnostics = write_hdf5(
        request.output_path, *mapped.domain, *run.results, identity);
    if (!write_diagnostics.empty()) {
        return {false, std::nullopt, std::move(write_diagnostics)};
    }

    return run;
}

}  // namespace fesa
