package chat import ( "context" "fmt" "eq2emu/internal/database" ) // DatabaseChannelManager implements ChannelDatabase interface using the correct database wrapper type DatabaseChannelManager struct { db *database.DB } // NewDatabaseChannelManager creates a new database channel manager using the correct wrapper func NewDatabaseChannelManager(db *database.DB) *DatabaseChannelManager { return &DatabaseChannelManager{ db: db, } } // LoadWorldChannels retrieves all persistent world channels from database func (dcm *DatabaseChannelManager) LoadWorldChannels(ctx context.Context) ([]ChatChannelData, error) { query := "SELECT `name`, `password`, `level_restriction`, `classes`, `races` FROM `channels`" var channels []ChatChannelData err := dcm.db.Query(query, func(row *database.Row) error { var channel ChatChannelData channel.Name = row.Text(0) if !row.IsNull(1) { channel.Password = row.Text(1) } channel.LevelRestriction = int32(row.Int64(2)) channel.ClassRestriction = int32(row.Int64(3)) channel.RaceRestriction = int32(row.Int64(4)) channels = append(channels, channel) return nil }) if err != nil { return nil, fmt.Errorf("failed to query channels: %w", err) } return channels, nil } // SaveChannel persists a channel to database (world channels only) func (dcm *DatabaseChannelManager) SaveChannel(ctx context.Context, channel ChatChannelData) error { // Insert or update channel query := ` INSERT OR REPLACE INTO channels (name, password, level_restriction, classes, races) VALUES (?, ?, ?, ?, ?)` var password *string if channel.Password != "" { password = &channel.Password } err := dcm.db.Exec(query, channel.Name, password, channel.LevelRestriction, channel.ClassRestriction, channel.RaceRestriction, ) if err != nil { return fmt.Errorf("failed to save channel %s: %w", channel.Name, err) } return nil } // DeleteChannel removes a channel from database func (dcm *DatabaseChannelManager) DeleteChannel(ctx context.Context, channelName string) error { query := "DELETE FROM channels WHERE name = ?" err := dcm.db.Exec(query, channelName) if err != nil { return fmt.Errorf("failed to delete channel %s: %w", channelName, err) } return nil } // EnsureChannelsTable creates the channels table if it doesn't exist func (dcm *DatabaseChannelManager) EnsureChannelsTable(ctx context.Context) error { query := ` CREATE TABLE IF NOT EXISTS channels ( name TEXT PRIMARY KEY, password TEXT, level_restriction INTEGER NOT NULL DEFAULT 0, classes INTEGER NOT NULL DEFAULT 0, races INTEGER NOT NULL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )` err := dcm.db.Exec(query) if err != nil { return fmt.Errorf("failed to create channels table: %w", err) } return nil } // GetChannelCount returns the total number of channels in the database func (dcm *DatabaseChannelManager) GetChannelCount(ctx context.Context) (int, error) { query := "SELECT COUNT(*) FROM channels" row, err := dcm.db.QueryRow(query) if err != nil { return 0, fmt.Errorf("failed to query channel count: %w", err) } if row == nil { return 0, nil } defer row.Close() count := row.Int(0) return count, nil } // GetChannelByName retrieves a specific channel by name func (dcm *DatabaseChannelManager) GetChannelByName(ctx context.Context, channelName string) (*ChatChannelData, error) { query := "SELECT `name`, `password`, `level_restriction`, `classes`, `races` FROM `channels` WHERE `name` = ?" row, err := dcm.db.QueryRow(query, channelName) if err != nil { return nil, fmt.Errorf("failed to query channel %s: %w", channelName, err) } if row == nil { return nil, fmt.Errorf("channel %s not found", channelName) } defer row.Close() var channel ChatChannelData channel.Name = row.Text(0) if !row.IsNull(1) { channel.Password = row.Text(1) } channel.LevelRestriction = int32(row.Int64(2)) channel.ClassRestriction = int32(row.Int64(3)) channel.RaceRestriction = int32(row.Int64(4)) return &channel, nil } // ListChannelNames returns a list of all channel names in the database func (dcm *DatabaseChannelManager) ListChannelNames(ctx context.Context) ([]string, error) { query := "SELECT name FROM channels ORDER BY name" var names []string err := dcm.db.Query(query, func(row *database.Row) error { name := row.Text(0) names = append(names, name) return nil }) if err != nil { return nil, fmt.Errorf("failed to query channel names: %w", err) } return names, nil } // UpdateChannelPassword updates just the password for a channel func (dcm *DatabaseChannelManager) UpdateChannelPassword(ctx context.Context, channelName, password string) error { query := "UPDATE channels SET password = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?" var passwordParam *string if password != "" { passwordParam = &password } err := dcm.db.Exec(query, passwordParam, channelName) if err != nil { return fmt.Errorf("failed to update password for channel %s: %w", channelName, err) } return nil } // UpdateChannelRestrictions updates the level, race, and class restrictions for a channel func (dcm *DatabaseChannelManager) UpdateChannelRestrictions(ctx context.Context, channelName string, levelRestriction, classRestriction, raceRestriction int32) error { query := "UPDATE channels SET level_restriction = ?, classes = ?, races = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?" err := dcm.db.Exec(query, levelRestriction, classRestriction, raceRestriction, channelName) if err != nil { return fmt.Errorf("failed to update restrictions for channel %s: %w", channelName, err) } return nil }