package guilds

import (
	"context"
	"fmt"
	"time"

	"eq2emu/internal/database"
)

// DatabaseGuildManager implements GuildDatabase interface using the existing database wrapper
type DatabaseGuildManager struct {
	db *database.DB
}

// NewDatabaseGuildManager creates a new database guild manager
func NewDatabaseGuildManager(db *database.DB) *DatabaseGuildManager {
	return &DatabaseGuildManager{
		db: db,
	}
}

// LoadGuilds retrieves all guilds from database
func (dgm *DatabaseGuildManager) LoadGuilds(ctx context.Context) ([]GuildData, error) {
	query := "SELECT `id`, `name`, `motd`, `level`, `xp`, `xp_needed`, `formed_on` FROM `guilds`"

	rows, err := dgm.db.QueryContext(ctx, query)
	if err != nil {
		return nil, fmt.Errorf("failed to query guilds: %w", err)
	}
	defer rows.Close()

	var guilds []GuildData
	for rows.Next() {
		var guild GuildData
		var motd *string
		var formedOnTimestamp int64

		err := rows.Scan(
			&guild.ID,
			&guild.Name,
			&motd,
			&guild.Level,
			&guild.EXPCurrent,
			&guild.EXPToNextLevel,
			&formedOnTimestamp,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild row: %w", err)
		}

		// Handle nullable MOTD field
		if motd != nil {
			guild.MOTD = *motd
		}

		// Convert timestamp to time
		guild.FormedDate = time.Unix(formedOnTimestamp, 0)

		guilds = append(guilds, guild)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild rows: %w", err)
	}

	return guilds, nil
}

// LoadGuild retrieves a specific guild from database
func (dgm *DatabaseGuildManager) LoadGuild(ctx context.Context, guildID int32) (*GuildData, error) {
	query := "SELECT `id`, `name`, `motd`, `level`, `xp`, `xp_needed`, `formed_on` FROM `guilds` WHERE `id` = ?"

	var guild GuildData
	var motd *string
	var formedOnTimestamp int64

	err := dgm.db.QueryRowContext(ctx, query, guildID).Scan(
		&guild.ID,
		&guild.Name,
		&motd,
		&guild.Level,
		&guild.EXPCurrent,
		&guild.EXPToNextLevel,
		&formedOnTimestamp,
	)
	if err != nil {
		return nil, fmt.Errorf("failed to load guild %d: %w", guildID, err)
	}

	// Handle nullable MOTD field
	if motd != nil {
		guild.MOTD = *motd
	}

	// Convert timestamp to time
	guild.FormedDate = time.Unix(formedOnTimestamp, 0)

	return &guild, nil
}

// LoadGuildMembers retrieves all members for a guild
func (dgm *DatabaseGuildManager) LoadGuildMembers(ctx context.Context, guildID int32) ([]GuildMemberData, error) {
	query := `SELECT char_id, guild_id, account_id, recruiter_id, name, guild_status, points,
			  adventure_class, adventure_level, tradeskill_class, tradeskill_level, rank,
			  member_flags, zone, join_date, last_login_date, note, officer_note,
			  recruiter_description, recruiter_picture_data, recruiting_show_adventure_class
			  FROM guild_members WHERE guild_id = ?`

	rows, err := dgm.db.QueryContext(ctx, query, guildID)
	if err != nil {
		return nil, fmt.Errorf("failed to query guild members for guild %d: %w", guildID, err)
	}
	defer rows.Close()

	var members []GuildMemberData
	for rows.Next() {
		var member GuildMemberData
		var joinDateTimestamp int64
		var lastLoginTimestamp int64
		var note, officerNote, recruiterDesc *string
		var pictureData []byte

		err := rows.Scan(
			&member.CharacterID,
			&member.GuildID,
			&member.AccountID,
			&member.RecruiterID,
			&member.Name,
			&member.GuildStatus,
			&member.Points,
			&member.AdventureClass,
			&member.AdventureLevel,
			&member.TradeskillClass,
			&member.TradeskillLevel,
			&member.Rank,
			&member.MemberFlags,
			&member.Zone,
			&joinDateTimestamp,
			&lastLoginTimestamp,
			&note,
			&officerNote,
			&recruiterDesc,
			&pictureData,
			&member.RecruitingShowAdventureClass,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild member row: %w", err)
		}

		// Handle nullable fields
		if note != nil {
			member.Note = *note
		}
		if officerNote != nil {
			member.OfficerNote = *officerNote
		}
		if recruiterDesc != nil {
			member.RecruiterDescription = *recruiterDesc
		}
		member.RecruiterPictureData = pictureData

		// Convert timestamps to time
		member.JoinDate = time.Unix(joinDateTimestamp, 0)
		member.LastLoginDate = time.Unix(lastLoginTimestamp, 0)

		members = append(members, member)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild member rows: %w", err)
	}

	return members, nil
}

// LoadGuildEvents retrieves events for a guild
func (dgm *DatabaseGuildManager) LoadGuildEvents(ctx context.Context, guildID int32) ([]GuildEventData, error) {
	query := `SELECT event_id, guild_id, date, type, description, locked
			  FROM guild_events WHERE guild_id = ?
			  ORDER BY event_id DESC LIMIT ?`

	rows, err := dgm.db.QueryContext(ctx, query, guildID, MaxEvents)
	if err != nil {
		return nil, fmt.Errorf("failed to query guild events for guild %d: %w", guildID, err)
	}
	defer rows.Close()

	var events []GuildEventData
	for rows.Next() {
		var event GuildEventData
		var dateTimestamp int64

		err := rows.Scan(
			&event.EventID,
			&event.GuildID,
			&dateTimestamp,
			&event.Type,
			&event.Description,
			&event.Locked,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild event row: %w", err)
		}

		// Convert timestamp to time
		event.Date = time.Unix(dateTimestamp, 0)

		events = append(events, event)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild event rows: %w", err)
	}

	return events, nil
}

// LoadGuildRanks retrieves custom rank names for a guild
func (dgm *DatabaseGuildManager) LoadGuildRanks(ctx context.Context, guildID int32) ([]GuildRankData, error) {
	query := "SELECT guild_id, rank, name FROM guild_ranks WHERE guild_id = ?"

	rows, err := dgm.db.QueryContext(ctx, query, guildID)
	if err != nil {
		return nil, fmt.Errorf("failed to query guild ranks for guild %d: %w", guildID, err)
	}
	defer rows.Close()

	var ranks []GuildRankData
	for rows.Next() {
		var rank GuildRankData

		err := rows.Scan(
			&rank.GuildID,
			&rank.Rank,
			&rank.Name,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild rank row: %w", err)
		}

		ranks = append(ranks, rank)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild rank rows: %w", err)
	}

	return ranks, nil
}

// LoadGuildPermissions retrieves permissions for a guild
func (dgm *DatabaseGuildManager) LoadGuildPermissions(ctx context.Context, guildID int32) ([]GuildPermissionData, error) {
	query := "SELECT guild_id, rank, permission, value FROM guild_permissions WHERE guild_id = ?"

	rows, err := dgm.db.QueryContext(ctx, query, guildID)
	if err != nil {
		return nil, fmt.Errorf("failed to query guild permissions for guild %d: %w", guildID, err)
	}
	defer rows.Close()

	var permissions []GuildPermissionData
	for rows.Next() {
		var permission GuildPermissionData

		err := rows.Scan(
			&permission.GuildID,
			&permission.Rank,
			&permission.Permission,
			&permission.Value,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild permission row: %w", err)
		}

		permissions = append(permissions, permission)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild permission rows: %w", err)
	}

	return permissions, nil
}

// LoadGuildEventFilters retrieves event filters for a guild
func (dgm *DatabaseGuildManager) LoadGuildEventFilters(ctx context.Context, guildID int32) ([]GuildEventFilterData, error) {
	query := "SELECT guild_id, event_id, category, value FROM guild_event_filters WHERE guild_id = ?"

	rows, err := dgm.db.QueryContext(ctx, query, guildID)
	if err != nil {
		return nil, fmt.Errorf("failed to query guild event filters for guild %d: %w", guildID, err)
	}
	defer rows.Close()

	var filters []GuildEventFilterData
	for rows.Next() {
		var filter GuildEventFilterData

		err := rows.Scan(
			&filter.GuildID,
			&filter.EventID,
			&filter.Category,
			&filter.Value,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild event filter row: %w", err)
		}

		filters = append(filters, filter)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild event filter rows: %w", err)
	}

	return filters, nil
}

// LoadGuildRecruiting retrieves recruiting settings for a guild
func (dgm *DatabaseGuildManager) LoadGuildRecruiting(ctx context.Context, guildID int32) ([]GuildRecruitingData, error) {
	query := "SELECT guild_id, flag, value FROM guild_recruiting WHERE guild_id = ?"

	rows, err := dgm.db.QueryContext(ctx, query, guildID)
	if err != nil {
		return nil, fmt.Errorf("failed to query guild recruiting for guild %d: %w", guildID, err)
	}
	defer rows.Close()

	var recruiting []GuildRecruitingData
	for rows.Next() {
		var recruit GuildRecruitingData

		err := rows.Scan(
			&recruit.GuildID,
			&recruit.Flag,
			&recruit.Value,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan guild recruiting row: %w", err)
		}

		recruiting = append(recruiting, recruit)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating guild recruiting rows: %w", err)
	}

	return recruiting, nil
}

// LoadPointHistory retrieves point history for a member
func (dgm *DatabaseGuildManager) LoadPointHistory(ctx context.Context, characterID int32) ([]PointHistoryData, error) {
	query := `SELECT char_id, date, modified_by, comment, points
			  FROM guild_point_history WHERE char_id = ?
			  ORDER BY date DESC LIMIT ?`

	rows, err := dgm.db.QueryContext(ctx, query, characterID, MaxPointHistory)
	if err != nil {
		return nil, fmt.Errorf("failed to query point history for character %d: %w", characterID, err)
	}
	defer rows.Close()

	var history []PointHistoryData
	for rows.Next() {
		var entry PointHistoryData
		var dateTimestamp int64

		err := rows.Scan(
			&entry.CharacterID,
			&dateTimestamp,
			&entry.ModifiedBy,
			&entry.Comment,
			&entry.Points,
		)
		if err != nil {
			return nil, fmt.Errorf("failed to scan point history row: %w", err)
		}

		// Convert timestamp to time
		entry.Date = time.Unix(dateTimestamp, 0)

		history = append(history, entry)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating point history rows: %w", err)
	}

	return history, nil
}

// SaveGuild saves guild basic data
func (dgm *DatabaseGuildManager) SaveGuild(ctx context.Context, guild *Guild) error {
	query := `INSERT OR REPLACE INTO guilds
			  (id, name, motd, level, xp, xp_needed, formed_on)
			  VALUES (?, ?, ?, ?, ?, ?, ?)`

	guildInfo := guild.GetGuildInfo()
	formedTimestamp := guild.GetFormedDate().Unix()

	_, err := dgm.db.ExecContext(ctx, query,
		guild.GetID(),
		guild.GetName(),
		guild.GetMOTD(),
		guild.GetLevel(),
		guild.GetEXPCurrent(),
		guild.GetEXPToNextLevel(),
		formedTimestamp,
	)
	if err != nil {
		return fmt.Errorf("failed to save guild %d: %w", guild.GetID(), err)
	}

	return nil
}

// SaveGuildMembers saves all guild members
func (dgm *DatabaseGuildManager) SaveGuildMembers(ctx context.Context, guildID int32, members []*GuildMember) error {
	if len(members) == 0 {
		return nil
	}

	// Use a transaction for atomic updates
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing members for this guild
	_, err = tx.ExecContext(ctx, "DELETE FROM guild_members WHERE guild_id = ?", guildID)
	if err != nil {
		return fmt.Errorf("failed to delete existing guild members: %w", err)
	}

	// Insert all members
	insertQuery := `INSERT INTO guild_members
					(char_id, guild_id, account_id, recruiter_id, name, guild_status, points,
					 adventure_class, adventure_level, tradeskill_class, tradeskill_level, rank,
					 member_flags, zone, join_date, last_login_date, note, officer_note,
					 recruiter_description, recruiter_picture_data, recruiting_show_adventure_class)
					VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`

	for _, member := range members {
		joinTimestamp := member.GetJoinDate().Unix()
		lastLoginTimestamp := member.GetLastLoginDate().Unix()

		_, err = tx.ExecContext(ctx, insertQuery,
			member.GetCharacterID(),
			guildID,
			member.AccountID,
			member.GetRecruiterID(),
			member.GetName(),
			member.GuildStatus,
			member.GetPoints(),
			member.GetAdventureClass(),
			member.GetAdventureLevel(),
			member.GetTradeskillClass(),
			member.GetTradeskillLevel(),
			member.GetRank(),
			member.GetMemberFlags(),
			member.GetZone(),
			joinTimestamp,
			lastLoginTimestamp,
			member.GetNote(),
			member.GetOfficerNote(),
			member.GetRecruiterDescription(),
			member.GetRecruiterPictureData(),
			member.RecruitingShowAdventureClass,
		)
		if err != nil {
			return fmt.Errorf("failed to insert guild member %d: %w", member.GetCharacterID(), err)
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// SaveGuildEvents saves guild events
func (dgm *DatabaseGuildManager) SaveGuildEvents(ctx context.Context, guildID int32, events []GuildEvent) error {
	if len(events) == 0 {
		return nil
	}

	query := `INSERT OR REPLACE INTO guild_events
			  (event_id, guild_id, date, type, description, locked)
			  VALUES (?, ?, ?, ?, ?, ?)`

	for _, event := range events {
		if !event.SaveNeeded {
			continue
		}

		dateTimestamp := event.Date.Unix()

		_, err := dgm.db.ExecContext(ctx, query,
			event.EventID,
			guildID,
			dateTimestamp,
			event.Type,
			event.Description,
			event.Locked,
		)
		if err != nil {
			return fmt.Errorf("failed to save guild event %d: %w", event.EventID, err)
		}
	}

	return nil
}

// SaveGuildRanks saves guild rank names
func (dgm *DatabaseGuildManager) SaveGuildRanks(ctx context.Context, guildID int32, ranks map[int8]string) error {
	// Use a transaction for atomic updates
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing ranks for this guild
	_, err = tx.ExecContext(ctx, "DELETE FROM guild_ranks WHERE guild_id = ?", guildID)
	if err != nil {
		return fmt.Errorf("failed to delete existing guild ranks: %w", err)
	}

	// Insert all ranks
	insertQuery := "INSERT INTO guild_ranks (guild_id, rank, name) VALUES (?, ?, ?)"

	for rank, name := range ranks {
		// Only save non-default rank names
		if defaultName, exists := DefaultRankNames[rank]; !exists || name != defaultName {
			_, err = tx.ExecContext(ctx, insertQuery, guildID, rank, name)
			if err != nil {
				return fmt.Errorf("failed to insert guild rank %d: %w", rank, err)
			}
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// SaveGuildPermissions saves guild permissions
func (dgm *DatabaseGuildManager) SaveGuildPermissions(ctx context.Context, guildID int32, permissions map[int8]map[int8]int8) error {
	// Use a transaction for atomic updates
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing permissions for this guild
	_, err = tx.ExecContext(ctx, "DELETE FROM guild_permissions WHERE guild_id = ?", guildID)
	if err != nil {
		return fmt.Errorf("failed to delete existing guild permissions: %w", err)
	}

	// Insert all permissions
	insertQuery := "INSERT INTO guild_permissions (guild_id, rank, permission, value) VALUES (?, ?, ?, ?)"

	for rank, rankPermissions := range permissions {
		for permission, value := range rankPermissions {
			_, err = tx.ExecContext(ctx, insertQuery, guildID, rank, permission, value)
			if err != nil {
				return fmt.Errorf("failed to insert guild permission %d/%d: %w", rank, permission, err)
			}
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// SaveGuildEventFilters saves guild event filters
func (dgm *DatabaseGuildManager) SaveGuildEventFilters(ctx context.Context, guildID int32, filters map[int8]map[int8]int8) error {
	// Use a transaction for atomic updates
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing filters for this guild
	_, err = tx.ExecContext(ctx, "DELETE FROM guild_event_filters WHERE guild_id = ?", guildID)
	if err != nil {
		return fmt.Errorf("failed to delete existing guild event filters: %w", err)
	}

	// Insert all filters
	insertQuery := "INSERT INTO guild_event_filters (guild_id, event_id, category, value) VALUES (?, ?, ?, ?)"

	for eventID, eventFilters := range filters {
		for category, value := range eventFilters {
			_, err = tx.ExecContext(ctx, insertQuery, guildID, eventID, category, value)
			if err != nil {
				return fmt.Errorf("failed to insert guild event filter %d/%d: %w", eventID, category, err)
			}
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// SaveGuildRecruiting saves guild recruiting settings
func (dgm *DatabaseGuildManager) SaveGuildRecruiting(ctx context.Context, guildID int32, flags, descTags map[int8]int8) error {
	// Use a transaction for atomic updates
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing recruiting settings for this guild
	_, err = tx.ExecContext(ctx, "DELETE FROM guild_recruiting WHERE guild_id = ?", guildID)
	if err != nil {
		return fmt.Errorf("failed to delete existing guild recruiting: %w", err)
	}

	// Insert recruiting flags
	insertQuery := "INSERT INTO guild_recruiting (guild_id, flag, value) VALUES (?, ?, ?)"

	for flag, value := range flags {
		_, err = tx.ExecContext(ctx, insertQuery, guildID, flag, value)
		if err != nil {
			return fmt.Errorf("failed to insert guild recruiting flag %d: %w", flag, err)
		}
	}

	// Insert description tags (with negative flag values to distinguish)
	for tag, value := range descTags {
		_, err = tx.ExecContext(ctx, insertQuery, guildID, -tag-1, value) // Negative to distinguish from flags
		if err != nil {
			return fmt.Errorf("failed to insert guild recruiting desc tag %d: %w", tag, err)
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// SavePointHistory saves point history for a member
func (dgm *DatabaseGuildManager) SavePointHistory(ctx context.Context, characterID int32, history []PointHistory) error {
	if len(history) == 0 {
		return nil
	}

	// Use a transaction for atomic updates
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete existing history for this character
	_, err = tx.ExecContext(ctx, "DELETE FROM guild_point_history WHERE char_id = ?", characterID)
	if err != nil {
		return fmt.Errorf("failed to delete existing point history: %w", err)
	}

	// Insert all history entries
	insertQuery := "INSERT INTO guild_point_history (char_id, date, modified_by, comment, points) VALUES (?, ?, ?, ?, ?)"

	for _, entry := range history {
		dateTimestamp := entry.Date.Unix()

		_, err = tx.ExecContext(ctx, insertQuery,
			characterID,
			dateTimestamp,
			entry.ModifiedBy,
			entry.Comment,
			entry.Points,
		)
		if err != nil {
			return fmt.Errorf("failed to insert point history entry: %w", err)
		}
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// GetGuildIDByCharacterID returns guild ID for a character
func (dgm *DatabaseGuildManager) GetGuildIDByCharacterID(ctx context.Context, characterID int32) (int32, error) {
	query := "SELECT guild_id FROM guild_members WHERE char_id = ?"

	var guildID int32
	err := dgm.db.QueryRowContext(ctx, query, characterID).Scan(&guildID)
	if err != nil {
		return 0, fmt.Errorf("failed to get guild ID for character %d: %w", characterID, err)
	}

	return guildID, nil
}

// CreateGuild creates a new guild
func (dgm *DatabaseGuildManager) CreateGuild(ctx context.Context, guildData GuildData) (int32, error) {
	query := `INSERT INTO guilds (name, motd, level, xp, xp_needed, formed_on)
			  VALUES (?, ?, ?, ?, ?, ?)`

	formedTimestamp := guildData.FormedDate.Unix()

	result, err := dgm.db.ExecContext(ctx, query,
		guildData.Name,
		guildData.MOTD,
		guildData.Level,
		guildData.EXPCurrent,
		guildData.EXPToNextLevel,
		formedTimestamp,
	)
	if err != nil {
		return 0, fmt.Errorf("failed to create guild: %w", err)
	}

	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("failed to get new guild ID: %w", err)
	}

	return int32(id), nil
}

// DeleteGuild removes a guild and all related data
func (dgm *DatabaseGuildManager) DeleteGuild(ctx context.Context, guildID int32) error {
	// Use a transaction for atomic deletion
	tx, err := dgm.db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	defer tx.Rollback()

	// Delete related data first (foreign key constraints)
	tables := []string{
		"guild_point_history",
		"guild_members",
		"guild_events",
		"guild_ranks",
		"guild_permissions",
		"guild_event_filters",
		"guild_recruiting",
	}

	for _, table := range tables {
		var query string
		if table == "guild_point_history" {
			// Special case: need to join with guild_members to get char_ids
			query = fmt.Sprintf("DELETE ph FROM %s ph JOIN guild_members gm ON ph.char_id = gm.char_id WHERE gm.guild_id = ?", table)
		} else {
			query = fmt.Sprintf("DELETE FROM %s WHERE guild_id = ?", table)
		}

		_, err = tx.ExecContext(ctx, query, guildID)
		if err != nil {
			return fmt.Errorf("failed to delete from %s: %w", table, err)
		}
	}

	// Finally delete the guild itself
	_, err = tx.ExecContext(ctx, "DELETE FROM guilds WHERE id = ?", guildID)
	if err != nil {
		return fmt.Errorf("failed to delete guild: %w", err)
	}

	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit transaction: %w", err)
	}

	return nil
}

// GetNextGuildID returns the next available guild ID
func (dgm *DatabaseGuildManager) GetNextGuildID(ctx context.Context) (int32, error) {
	query := "SELECT COALESCE(MAX(id), 0) + 1 FROM guilds"

	var nextID int32
	err := dgm.db.QueryRowContext(ctx, query).Scan(&nextID)
	if err != nil {
		return 0, fmt.Errorf("failed to get next guild ID: %w", err)
	}

	return nextID, nil
}

// GetNextEventID returns the next available event ID for a guild
func (dgm *DatabaseGuildManager) GetNextEventID(ctx context.Context, guildID int32) (int64, error) {
	query := "SELECT COALESCE(MAX(event_id), 0) + 1 FROM guild_events WHERE guild_id = ?"

	var nextID int64
	err := dgm.db.QueryRowContext(ctx, query, guildID).Scan(&nextID)
	if err != nil {
		return 0, fmt.Errorf("failed to get next event ID for guild %d: %w", guildID, err)
	}

	return nextID, nil
}

// EnsureGuildTables creates the guild tables if they don't exist
func (dgm *DatabaseGuildManager) EnsureGuildTables(ctx context.Context) error {
	queries := []string{
		`CREATE TABLE IF NOT EXISTS guilds (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			name TEXT NOT NULL UNIQUE,
			motd TEXT,
			level INTEGER NOT NULL DEFAULT 1,
			xp INTEGER NOT NULL DEFAULT 111,
			xp_needed INTEGER NOT NULL DEFAULT 2521,
			formed_on INTEGER NOT NULL,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
		)`,
		`CREATE TABLE IF NOT EXISTS guild_members (
			char_id INTEGER NOT NULL,
			guild_id INTEGER NOT NULL,
			account_id INTEGER NOT NULL DEFAULT 0,
			recruiter_id INTEGER NOT NULL DEFAULT 0,
			name TEXT NOT NULL,
			guild_status INTEGER NOT NULL DEFAULT 0,
			points REAL NOT NULL DEFAULT 0.0,
			adventure_class INTEGER NOT NULL DEFAULT 0,
			adventure_level INTEGER NOT NULL DEFAULT 1,
			tradeskill_class INTEGER NOT NULL DEFAULT 0,
			tradeskill_level INTEGER NOT NULL DEFAULT 1,
			rank INTEGER NOT NULL DEFAULT 7,
			member_flags INTEGER NOT NULL DEFAULT 0,
			zone TEXT NOT NULL DEFAULT '',
			join_date INTEGER NOT NULL,
			last_login_date INTEGER NOT NULL,
			note TEXT NOT NULL DEFAULT '',
			officer_note TEXT NOT NULL DEFAULT '',
			recruiter_description TEXT NOT NULL DEFAULT '',
			recruiter_picture_data BLOB,
			recruiting_show_adventure_class INTEGER NOT NULL DEFAULT 1,
			PRIMARY KEY (char_id),
			FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS guild_events (
			event_id INTEGER NOT NULL,
			guild_id INTEGER NOT NULL,
			date INTEGER NOT NULL,
			type INTEGER NOT NULL,
			description TEXT NOT NULL,
			locked INTEGER NOT NULL DEFAULT 0,
			PRIMARY KEY (event_id, guild_id),
			FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS guild_ranks (
			guild_id INTEGER NOT NULL,
			rank INTEGER NOT NULL,
			name TEXT NOT NULL,
			PRIMARY KEY (guild_id, rank),
			FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS guild_permissions (
			guild_id INTEGER NOT NULL,
			rank INTEGER NOT NULL,
			permission INTEGER NOT NULL,
			value INTEGER NOT NULL,
			PRIMARY KEY (guild_id, rank, permission),
			FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS guild_event_filters (
			guild_id INTEGER NOT NULL,
			event_id INTEGER NOT NULL,
			category INTEGER NOT NULL,
			value INTEGER NOT NULL,
			PRIMARY KEY (guild_id, event_id, category),
			FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS guild_recruiting (
			guild_id INTEGER NOT NULL,
			flag INTEGER NOT NULL,
			value INTEGER NOT NULL,
			PRIMARY KEY (guild_id, flag),
			FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE
		)`,
		`CREATE TABLE IF NOT EXISTS guild_point_history (
			char_id INTEGER NOT NULL,
			date INTEGER NOT NULL,
			modified_by TEXT NOT NULL,
			comment TEXT NOT NULL,
			points REAL NOT NULL,
			PRIMARY KEY (char_id, date),
			FOREIGN KEY (char_id) REFERENCES guild_members(char_id) ON DELETE CASCADE
		)`,
	}

	for i, query := range queries {
		_, err := dgm.db.ExecContext(ctx, query)
		if err != nil {
			return fmt.Errorf("failed to create guild table %d: %w", i+1, err)
		}
	}

	// Create indexes for better performance
	indexes := []string{
		`CREATE INDEX IF NOT EXISTS idx_guild_members_guild_id ON guild_members(guild_id)`,
		`CREATE INDEX IF NOT EXISTS idx_guild_members_char_id ON guild_members(char_id)`,
		`CREATE INDEX IF NOT EXISTS idx_guild_events_guild_id ON guild_events(guild_id)`,
		`CREATE INDEX IF NOT EXISTS idx_guild_events_date ON guild_events(date)`,
		`CREATE INDEX IF NOT EXISTS idx_guild_point_history_char_id ON guild_point_history(char_id)`,
		`CREATE INDEX IF NOT EXISTS idx_guilds_name ON guilds(name)`,
		`CREATE INDEX IF NOT EXISTS idx_guild_members_rank ON guild_members(rank)`,
		`CREATE INDEX IF NOT EXISTS idx_guild_members_last_login ON guild_members(last_login_date)`,
	}

	for i, query := range indexes {
		_, err := dgm.db.ExecContext(ctx, query)
		if err != nil {
			return fmt.Errorf("failed to create guild index %d: %w", i+1, err)
		}
	}

	return nil
}
