package factions

import (
	"testing"
)

func TestNewFaction(t *testing.T) {
	faction := NewFaction(1, "Test Faction", "TestType", "A test faction")
	if faction == nil {
		t.Fatal("NewFaction returned nil")
	}

	if faction.ID != 1 {
		t.Errorf("Expected ID 1, got %d", faction.ID)
	}

	if faction.Name != "Test Faction" {
		t.Errorf("Expected name 'Test Faction', got '%s'", faction.Name)
	}

	if faction.Type != "TestType" {
		t.Errorf("Expected type 'TestType', got '%s'", faction.Type)
	}

	if faction.Description != "A test faction" {
		t.Errorf("Expected description 'A test faction', got '%s'", faction.Description)
	}
}

func TestMasterFactionList(t *testing.T) {
	mfl := NewMasterFactionList()
	if mfl == nil {
		t.Fatal("NewMasterFactionList returned nil")
	}

	// Test adding faction
	faction := NewFaction(100, "Test Faction", "Test", "Test faction")
	err := mfl.AddFaction(faction)
	if err != nil {
		t.Fatalf("Failed to add faction: %v", err)
	}

	// Test getting faction
	retrieved := mfl.GetFaction(100)
	if retrieved == nil {
		t.Error("Failed to retrieve added faction")
	} else if retrieved.Name != "Test Faction" {
		t.Errorf("Expected name 'Test Faction', got '%s'", retrieved.Name)
	}

	// Test getting all factions
	factions := mfl.GetAllFactions()
	if len(factions) == 0 {
		t.Error("Expected at least one faction")
	}
}

func TestPlayerFaction(t *testing.T) {
	mfl := NewMasterFactionList()
	pf := NewPlayerFaction(mfl)
	if pf == nil {
		t.Fatal("NewPlayerFaction returned nil")
	}

	// Use faction ID > 10 since IDs <= 10 are special factions that always return 0
	testFactionID := int32(100)

	// Test setting faction value
	pf.SetFactionValue(testFactionID, 1000)
	value := pf.GetFactionValue(testFactionID)
	if value != 1000 {
		t.Errorf("Expected faction value 1000, got %d", value)
	}

	// Test faction modification
	pf.IncreaseFaction(testFactionID, 500)
	value = pf.GetFactionValue(testFactionID)
	if value != 1500 {
		t.Errorf("Expected faction value 1500 after increase, got %d", value)
	}

	pf.DecreaseFaction(testFactionID, 200)
	value = pf.GetFactionValue(testFactionID)
	if value != 1300 {
		t.Errorf("Expected faction value 1300 after decrease, got %d", value)
	}

	// Test consideration calculation
	consideration := pf.GetCon(testFactionID)
	if consideration < -4 || consideration > 4 {
		t.Errorf("Consideration %d is out of valid range [-4, 4]", consideration)
	}
}

func TestFactionRelations(t *testing.T) {
	mfl := NewMasterFactionList()

	// Add test factions
	faction1 := NewFaction(1, "Faction 1", "Test", "Test faction 1")
	faction2 := NewFaction(2, "Faction 2", "Test", "Test faction 2")
	faction3 := NewFaction(3, "Faction 3", "Test", "Test faction 3")

	mfl.AddFaction(faction1)
	mfl.AddFaction(faction2)
	mfl.AddFaction(faction3)

	// Test hostile relations
	mfl.AddHostileFaction(1, 2)

	// Check if faction 2 is in the hostile list for faction 1
	hostiles := mfl.GetHostileFactions(1)
	isHostile := false
	for _, hostileID := range hostiles {
		if hostileID == 2 {
			isHostile = true
			break
		}
	}
	if !isHostile {
		t.Error("Expected faction 2 to be hostile to faction 1")
	}

	// Test friendly relations
	mfl.AddFriendlyFaction(1, 3)

	// Check if faction 3 is in the friendly list for faction 1
	friendlies := mfl.GetFriendlyFactions(1)
	isFriendly := false
	for _, friendlyID := range friendlies {
		if friendlyID == 3 {
			isFriendly = true
			break
		}
	}
	if !isFriendly {
		t.Error("Expected faction 3 to be friendly to faction 1")
	}

	// Test removing relations - need to implement RemoveHostileFaction first
	// For now, just verify current state
	hostiles = mfl.GetHostileFactions(1)
	isHostile = false
	for _, hostileID := range hostiles {
		if hostileID == 2 {
			isHostile = true
			break
		}
	}
	if !isHostile {
		t.Error("Expected faction 2 to still be hostile to faction 1 (removal not implemented)")
	}
}


func TestFactionValidation(t *testing.T) {
	mfl := NewMasterFactionList()

	// Test nil faction
	err := mfl.AddFaction(nil)
	if err == nil {
		t.Error("Expected error when adding nil faction")
	}

	// Test invalid faction ID
	faction := NewFaction(0, "Invalid", "Test", "Invalid faction")
	err = mfl.AddFaction(faction)
	if err == nil {
		t.Error("Expected error when adding faction with ID 0")
	}

	// Test empty name
	faction = NewFaction(1, "", "Test", "Empty name faction")
	err = mfl.AddFaction(faction)
	if err == nil {
		t.Error("Expected error when adding faction with empty name")
	}
}