/**
 * Defines utility functions for testing CPER-JSON IR output from the cper-parse library.
 *
 * Author: Lawrence.Tang@arm.com
 **/

#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <filesystem>
#include "test-utils.hpp"

#include <libcper/BaseTypes.h>
#include <libcper/generator/cper-generate.h>

namespace fs = std::filesystem;

// Truly optional properties that shouldn't be added to "required" field for
// validating the entire schema with validationbits=1
const static std::map<std::string, std::vector<std::string> >
	optional_properties_map = {
		{ "./sections/cper-arm-processor.json",
		  { "vendorSpecificInfo" } },
		{ "./cper-json-section-log.json", { "header" } },
		{ "./sections/cper-cxl-protocol.json",
		  { "capabilityStructure", "deviceSerial" } },
		{ "./sections/cper-generic-dmar.json",
		  { "faultReason", "description" } },
		{ "./sections/cper-cxl-component.json",
		  { "cxlComponentEventLog" } },
	};

nlohmann::json loadJson(const char *filePath)
{
	std::ifstream file(filePath);
	if (!file.is_open()) {
		std::cerr << "Failed to open file: " << filePath << std::endl;
	}
	nlohmann::json out = nlohmann::json::parse(file, nullptr, false);
	return out;
}

//Returns a ready-for-use memory stream containing a CPER record with the given sections inside.
FILE *generate_record_memstream(const char **types, UINT16 num_types,
				char **buf, size_t *buf_size,
				int single_section,
				GEN_VALID_BITS_TEST_TYPE validBitsType)
{
	//Open a memory stream.
	FILE *stream = open_memstream(buf, buf_size);

	//Generate a section to the stream, close & return.
	if (!single_section) {
		generate_cper_record(const_cast<char **>(types), num_types,
				     stream, validBitsType);
	} else {
		generate_single_section_record(const_cast<char *>(types[0]),
					       stream, validBitsType);
	}
	fclose(stream);

	//Return fmemopen() buffer for reading.
	return fmemopen(*buf, *buf_size, "r");
}

void iterate_make_required_props(nlohmann::json &jsonSchema,
				 std::vector<std::string> &optional_props)
{
	//id
	const auto it_id = jsonSchema.find("$id");
	if (it_id != jsonSchema.end()) {
		auto id_strptr = it_id->get_ptr<const std::string *>();
		std::string id_str = *id_strptr;
		if (id_str.find("header") != std::string::npos ||
		    id_str.find("section-descriptor") != std::string::npos) {
			return;
		}
	}
	//oneOf
	const auto it_oneof = jsonSchema.find("oneOf");
	if (it_oneof != jsonSchema.end()) {
		//Iterate over oneOf properties
		for (auto &oneOfProp : *it_oneof) {
			iterate_make_required_props(oneOfProp, optional_props);
		}
	}

	//items
	const auto it_items = jsonSchema.find("items");
	if (it_items != jsonSchema.end()) {
		iterate_make_required_props(*it_items, optional_props);
	}
	//required
	const auto it_req = jsonSchema.find("required");
	if (it_req == jsonSchema.end()) {
		return;
	}

	//properties
	const auto it_prop = jsonSchema.find("properties");
	if (it_prop == jsonSchema.end()) {
		return;
	}
	nlohmann::json &propertyFields = *it_prop;
	nlohmann::json::array_t property_list;
	if (propertyFields.is_object()) {
		for (auto &[key, value] : propertyFields.items()) {
			const auto it_find_opt_prop =
				std::find(optional_props.begin(),
					  optional_props.end(), key);
			if (it_find_opt_prop == optional_props.end()) {
				//Add to list if property is not optional
				property_list.push_back(key);
			}

			iterate_make_required_props(value, optional_props);
		}
	}

	*it_req = property_list;
}

// Document loader callback function
const nlohmann::json *documentLoader(const std::string &uri)
{
	// Load the schema from a file
	nlohmann::json *ref_schema = new nlohmann::json;
	*ref_schema = loadJson(uri.c_str());
	if (ref_schema->is_discarded()) {
		std::cerr << "Could not open schema file: " << uri << std::endl;
	}
	std::vector<std::string> opt = {};
	const auto it_optional_file = optional_properties_map.find(uri);
	if (it_optional_file != optional_properties_map.end()) {
		opt = it_optional_file->second;
	}
	iterate_make_required_props(*ref_schema, opt);

	return ref_schema;
}

// Document release callback function
void documentRelease(const nlohmann::json *adapter)
{
	delete adapter; // Free the adapter memory
}

int schema_validate_from_file(const char *schema_file_path,
			      nlohmann::json &jsonData,
			      std::string &error_message)
{
	// Load the schema
	nlohmann::json schema_root = loadJson(schema_file_path);
	if (schema_root.is_discarded()) {
		std::cerr << "Could not open schema file: " << schema_file_path
			  << std::endl;
		return 0;
	}

	fs::path pathObj(schema_file_path);
	fs::path base_path = pathObj.parent_path();
	try {
		fs::current_path(base_path);
		// std::cout << "Changed directory to: " << fs::current_path()
		// 	  << std::endl;
	} catch (const fs::filesystem_error &e) {
		std::cerr << "Filesystem error: " << e.what() << std::endl;
	}

	// Parse the json schema into an internal schema format
	valijson::Schema schema;
	valijson::SchemaParser parser;
	valijson::adapters::NlohmannJsonAdapter schemaDocumentAdapter(
		schema_root);

	// Set up callbacks for resolving external references
	try {
		parser.populateSchema(schemaDocumentAdapter, schema,
				      documentLoader, documentRelease);
	} catch (std::exception &e) {
		std::cerr << "Failed to parse schema: " << e.what()
			  << std::endl;
		return 0;
	}

	// Perform validation
	valijson::Validator validator(valijson::Validator::kStrongTypes);
	valijson::ValidationResults results;
	valijson::adapters::NlohmannJsonAdapter targetDocumentAdapter(jsonData);
	if (!validator.validate(schema, targetDocumentAdapter, &results)) {
		std::cerr << "Validation failed." << std::endl;
		valijson::ValidationResults::Error error;
		unsigned int errorNum = 1;
		while (results.popError(error)) {
			std::string context;
			std::vector<std::string>::iterator itr =
				error.context.begin();
			for (; itr != error.context.end(); itr++) {
				context += *itr;
			}

			std::cout << "Error #" << errorNum << std::endl
				  << "  context: " << context << std::endl
				  << "  desc:    " << error.description
				  << std::endl;
			++errorNum;
		}
		return 0;
	}

	error_message = "Schema validation successful";
	return 1;
}
