package titles

import (
	"os"
	"testing"

	"eq2emu/internal/database"
)

func TestNewTitle(t *testing.T) {
	title := NewTitle(1, "Test Title")
	if title == nil {
		t.Fatal("NewTitle returned nil")
	}

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

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

	if title.Position != TitlePositionSuffix {
		t.Errorf("Expected default position %d, got %d", TitlePositionSuffix, title.Position)
	}
}

func TestMasterTitlesList(t *testing.T) {
	mtl := NewMasterTitlesList()
	if mtl == nil {
		t.Fatal("NewMasterTitlesList returned nil")
	}

	// Test default titles are loaded
	citizen := mtl.GetTitle(TitleIDCitizen)
	if citizen == nil {
		t.Error("Expected Citizen title to be loaded by default")
	}

	visitor := mtl.GetTitle(TitleIDVisitor)
	if visitor == nil {
		t.Error("Expected Visitor title to be loaded by default")
	}

	// Test adding new title
	testTitle := NewTitle(100, "Test Title")
	err := mtl.AddTitle(testTitle)
	if err != nil {
		t.Fatalf("Failed to add title: %v", err)
	}

	retrieved := mtl.GetTitle(100)
	if retrieved == nil {
		t.Error("Failed to retrieve added title")
	} else if retrieved.Name != "Test Title" {
		t.Errorf("Expected retrieved title name 'Test Title', got '%s'", retrieved.Name)
	}
}

func TestPlayerTitlesList(t *testing.T) {
	mtl := NewMasterTitlesList()
	ptl := NewPlayerTitlesList(123, mtl)

	if ptl == nil {
		t.Fatal("NewPlayerTitlesList returned nil")
	}

	// Test adding title
	err := ptl.AddTitle(TitleIDCitizen, 0, 0)
	if err != nil {
		t.Fatalf("Failed to add title to player: %v", err)
	}

	// Test getting titles
	titles := ptl.GetTitles()
	if len(titles) != 1 {
		t.Errorf("Expected 1 title, got %d", len(titles))
	}

	// Test setting active title
	err = ptl.SetActiveTitle(TitleIDCitizen, TitlePositionSuffix)
	if err != nil {
		t.Fatalf("Failed to set active title: %v", err)
	}

	// Test getting active titles
	activePrefix, activeSuffix := ptl.GetActiveTitles()
	if activePrefix != 0 {
		t.Errorf("Expected no active prefix, got %d", activePrefix)
	}
	if activeSuffix != TitleIDCitizen {
		t.Errorf("Expected active suffix %d, got %d", TitleIDCitizen, activeSuffix)
	}
}

func TestTitleManager(t *testing.T) {
	tm := NewTitleManager()
	if tm == nil {
		t.Fatal("NewTitleManager returned nil")
	}

	// Test getting player titles
	playerTitles := tm.GetPlayerTitles(456)
	if playerTitles == nil {
		t.Error("GetPlayerTitles returned nil")
	}

	// Test adding title for player
	err := tm.GrantTitle(456, TitleIDCitizen, 0)
	if err != nil {
		t.Fatalf("Failed to grant title: %v", err)
	}

	// Verify title was granted
	playerTitles = tm.GetPlayerTitles(456)
	titles := playerTitles.GetTitles()
	if len(titles) != 1 {
		t.Errorf("Expected 1 title for player, got %d", len(titles))
	}
}

func TestTitleDatabaseIntegration(t *testing.T) {
	// Create temporary database
	tempFile := "test_titles.db"
	defer os.Remove(tempFile)

	db, err := database.Open(tempFile)
	if err != nil {
		t.Fatalf("Failed to open database: %v", err)
	}
	defer db.Close()

	// Test master list database operations
	mtl := NewMasterTitlesList()
	
	// Test saving to database
	err = mtl.SaveToDatabase(db)
	if err != nil {
		t.Fatalf("Failed to save master titles to database: %v", err)
	}

	// Create new master list and load from database
	mtl2 := &MasterTitlesList{
		titles:        make(map[int32]*Title),
		categorized:   make(map[string][]*Title),
		bySource:      make(map[int32][]*Title),
		byRarity:      make(map[int32][]*Title),
		byAchievement: make(map[uint32]*Title),
		nextID:        1,
	}

	err = mtl2.LoadFromDatabase(db)
	if err != nil {
		t.Fatalf("Failed to load master titles from database: %v", err)
	}

	// Verify titles were loaded
	citizen := mtl2.GetTitle(TitleIDCitizen)
	if citizen == nil {
		t.Error("Failed to load Citizen title from database")
	}

	// Test player titles database operations
	ptl := NewPlayerTitlesList(789, mtl)
	err = ptl.AddTitle(TitleIDCitizen, 0, 0)
	if err != nil {
		t.Fatalf("Failed to add title to player: %v", err)
	}

	// Save player titles
	err = ptl.SaveToDatabase(db)
	if err != nil {
		t.Fatalf("Failed to save player titles to database: %v", err)
	}

	// Load player titles
	ptl2 := NewPlayerTitlesList(789, mtl)
	err = ptl2.LoadFromDatabase(db)
	if err != nil {
		t.Fatalf("Failed to load player titles from database: %v", err)
	}

	// Verify player titles were loaded
	titles := ptl2.GetTitles()
	if len(titles) != 1 {
		t.Errorf("Expected 1 loaded title, got %d", len(titles))
	}
}

func TestTitleValidation(t *testing.T) {
	mtl := NewMasterTitlesList()
	
	// Test nil title
	err := mtl.AddTitle(nil)
	if err == nil {
		t.Error("Expected error when adding nil title")
	}

	// Test duplicate ID
	title1 := NewTitle(999, "Title 1")
	title2 := NewTitle(999, "Title 2")
	
	err = mtl.AddTitle(title1)
	if err != nil {
		t.Fatalf("Failed to add first title: %v", err)
	}

	err = mtl.AddTitle(title2)
	if err == nil {
		t.Error("Expected error when adding title with duplicate ID")
	}
}