extends "res://addons/gut/test.gd"

const NewGame = preload("res://scripts/newgame/new_game.gd")
const ContentDB = preload("res://scripts/content/content_db.gd")

var world


func before_each():
	world = ContentDB.new()
	world.load_from(ContentDB.default_content_root())


func _deserter() -> Dictionary:
	return ContentDB.load_json(ContentDB.origin_path("deserter"))


func _rng() -> RandomNumberGenerator:
	var r := RandomNumberGenerator.new()
	r.seed = 7
	return r


func _build(creation: Dictionary) -> Dictionary:
	return NewGame.construct(_deserter(), world, creation, _rng())


func test_construct_succeeds():
	var res := _build({"name": "Aldric", "class_id": "sellsword"})
	assert_true(res["ok"], str(res["errors"]))


func test_numeric_luck_absent_from_log():
	var res := _build({"name": "Aldric", "class_id": "sellsword"})
	var pd: Dictionary = res["log"].player.to_dict()
	assert_false("luck" in pd)
	assert_eq(pd.keys().size(), 3)
	assert_true(res["state"].luck >= Luck.MIN and res["state"].luck <= Luck.MAX)


func test_inventory_and_dispo_land_in_state_not_log():
	var res := _build({"name": "Aldric", "class_id": "sellsword"})
	assert_eq(res["state"].inventory.get("coin", 0), 3)
	assert_eq(res["state"].inventory.get("worn_shortsword", 0), 1)
	assert_false("inventory" in res["log"].to_dict())


func test_companion_dispositions_from_overrides():
	var res := _build({"name": "Aldric", "class_id": "sellsword"})
	assert_eq(res["log"].party_member("brannoc_thane").disposition, 40)
	assert_eq(res["log"].party_member("cadwyn_vell").disposition, 15)


func test_situation_and_facts_seeded():
	var res := _build({"name": "Aldric", "class_id": "sellsword"})
	assert_eq(res["log"].recent_events.size(), 2)
	assert_true("the player deserted the Iron Kettle mercenary company" in res["log"].established_facts)
	assert_eq(res["log"].humiliations.size(), 0)


func test_active_quest_resolved_from_world():
	var res := _build({"name": "Aldric", "class_id": "sellsword"})
	assert_eq(res["log"].active_quests.size(), 1)
	assert_eq(res["log"].active_quests[0].id, "find_the_ledger")
	assert_eq(res["log"].active_quests[0].status, "active")


func test_null_start_quest_yields_no_quest():
	var o := _deserter()
	o["start_quest_id"] = null
	var res := NewGame.construct(o, world, {"name": "X", "class_id": "sellsword"}, _rng())
	assert_eq(res["log"].active_quests.size(), 0)


func test_class_not_allowed_is_rejected():
	var res := _build({"name": "X", "class_id": "berserker"})
	assert_false(res["ok"])
	assert_true(res["errors"].size() > 0)
	assert_null(res["log"])


func test_unresolved_origin_is_rejected():
	var o := _deserter()
	o["start_location_id"] = "nowhere"
	var res := NewGame.construct(o, world, {"name": "X", "class_id": "sellsword"}, _rng())
	assert_false(res["ok"])
	assert_true("unresolved ref: location:nowhere" in res["errors"])


func test_empty_name_is_rejected():
	var missing_name := _build({"class_id": "sellsword"})
	assert_false(missing_name["ok"])
	assert_true(missing_name["errors"].size() > 0)
	assert_null(missing_name["log"])

	var whitespace_name := _build({"name": "   ", "class_id": "sellsword"})
	assert_false(whitespace_name["ok"])
	assert_true(whitespace_name["errors"].size() > 0)
	assert_null(whitespace_name["log"])


func test_non_companion_override_goes_to_state_not_log():
	world.npcs["oda_fenn"] = {"id": "oda_fenn", "name": "Oda Fenn", "role": "npc"}
	var o := _deserter()
	o["disposition_overrides"] = {"brannoc_thane": 40, "oda_fenn": -25}
	var res := NewGame.construct(o, world, {"name": "X", "class_id": "sellsword"}, _rng())
	assert_true(res["ok"], str(res["errors"]))
	assert_eq(res["state"].npc_dispositions["oda_fenn"], -25)
	assert_null(res["log"].party_member("oda_fenn"))
	for m in res["log"].to_dict()["party"]:
		assert_ne(m["id"], "oda_fenn")
	assert_eq(res["log"].party_member("brannoc_thane").disposition, 40)
