#ifndef EDITSCENE_MARKOV_NAME_GENERATOR_HPP
#define EDITSCENE_MARKOV_NAME_GENERATOR_HPP
#pragma once

#include <nlohmann/json.hpp>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <random>

/**
 * Character-level Markov chain name generator.
 *
 * Learns from example names and generates new ones using
 * order-2 (trigram) transitions with an order-1 (bigram) fallback.
 *
 * Names are learned in lowercase and generated title-cased.
 */
class MarkovNameGenerator {
public:
	MarkovNameGenerator();

	/** Feed a single name into the model. */
	void learn(const std::string &name);

	/** Feed many names at once. */
	void learn(const std::vector<std::string> &names);

	/**
	 * Generate a new name.
	 *
	 * @param minLen   minimum length (default 3)
	 * @param maxLen   maximum length (default 12)
	 * @param exclude  optional set of names to avoid generating
	 * @return generated name, or empty string if model is empty
	 */
	std::string generate(int minLen = 3, int maxLen = 12,
			     const std::unordered_set<std::string> *exclude = nullptr)
		const;

	/** Generate multiple candidates at once. */
	std::vector<std::string> generateMany(int count, int minLen = 3,
					      int maxLen = 12,
					      const std::unordered_set<std::string> *exclude = nullptr)
		const;

	/** Reset the model. */
	void clear();

	/** True if no names have been learned. */
	bool empty() const;

	/** Serialize model to JSON. */
	void saveToJson(nlohmann::json &j) const;

	/** Load model from JSON. */
	void loadFromJson(const nlohmann::json &j);

private:
	/* Order-2: prefix of 2 chars -> { next_char : weight } */
	std::unordered_map<std::string,
			   std::unordered_map<char, int>>
		m_order2;

	/* Order-1: single char -> { next_char : weight } */
	std::unordered_map<char, std::unordered_map<char, int>>
		m_order1;

	/* Valid starting bigrams (the first real 2 chars). */
	std::unordered_map<std::string, int> m_starters;

	/* Random state */
	mutable std::mt19937 m_rng;

	/* Weighted random pick from a frequency map. */
	char pickNext(const std::unordered_map<char, int> &freqs) const;
	std::string pickStarter() const;

	/* Convert first letter to uppercase. */
	static std::string titleCase(const std::string &s);
};

#endif // EDITSCENE_MARKOV_NAME_GENERATOR_HPP
