package player import ( "database/sql" "log" "strings" "time" "github.com/google/uuid" "github.com/lib/pq" ) type User struct { UUID string `db:"uuid" sql:"VARCHAR(255)" index:"true"` Username string `db:"username" sql:"VARCHAR(100)"` Email string `db:"email" sql:"VARCHAR(255)" index:"true"` lastname sql.NullString `db:"lastname" sql:"VARCHAR(100)"` firstname sql.NullString `db:"firstname" sql:"VARCHAR(100)"` password string `db:"password_hash" sql:"VARCHAR(255)"` phone sql.NullString `db:"phone" sql:"VARCHAR(20)"` avatarURL sql.NullString `db:"avatar_url" sql:"VARCHAR(255)"` IsActive sql.NullBool `db:"is_active" sql:"BOOLEAN"` birthday *time.Time `db:"birthday" sql:"DATE"` Created_at *time.Time `db:"created_at" sql:"TIMESTAMP"` updatedAt *time.Time `db:"updated_at" sql:"TIMESTAMP"` LastLogin *time.Time `db:"last_login" sql:"TIMESTAMP"` Role []string `ignore:"true"` // wird NICHT in der DB angelegt } type Roles struct { ID int `db:"id" sql:"SERIAL PRIMARY KEY"` PlayerID string `db:"player_id" sql:"UUID"` Role []string `db:"role" sql:"TEXT[]"` } // const PlayerTable = ` // CREATE TABLE IF NOT EXISTS users ( // id uuid PRIMARY KEY, // username VARCHAR(100) NOT NULL, // lastname VARCHAR(100) NOT NULL, // fistname VARCHAR(100) NOT NULL, // email VARCHAR(100) NOT NULL UNIQUE, // password_hash VARCHAR(255) NOT NULL, // created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // last_login TIMESTAMP, // phone VARCHAR(20), // avatar_url VARCHAR(255), // is_active BOOLEAN NOT NULL DEFAULT TRUE // ); // ` // const RoleTable = ` // CREATE TABLE IF NOT EXISTS roles ( // id SERIAL PRIMARY KEY, // player_id uuid NOT NULL, // role VARCHAR(50) NOT NULL CHECK (role IN ('player', 'admin')), // FOREIGN KEY (player_id) REFERENCES users(id) ON DELETE CASCADE // ); //` type Team struct { ID string `json:"id"` Name string `json:"name"` Players []User `json:"users"` // Players in the team // Matches []Match `json:"matches"` // Matches the team is involved in MatchesWon int `json:"matchesWon"` // Number of matches won by the team MatchesLost int `json:"matchesLost"` // Number of matches lost by the team MatchesDrawn int `json:"matchesDrawn"` // Number of matches drawn by the team MatchesPlayed int `json:"matchesPlayed"` // Total matches played by the team MatchesPlayedCount int `json:"matchesPlayedCount"` // Total matches played by the team } // type Player struct { // ID string `json:"id"` // Name string `json:"name"` // Email string `json:"email"` // Password string `json:"password,omitempty"` // Password is optional for responses // Role string `json:"role"` // e.g., "player","organizer" // Teams []Team `json:"teams"` // Teams the player is part of // // Tournaments []Tournament `json:"tournaments"` // Tournaments the player is registered in // OwnedTournaments []string `json:"ownedTournaments"` // Tournaments the player is organizing // ParticipatedTournaments []string `json:"participatedTournaments"` // Tournaments the player is participating in // } type PlayerListResponse struct { Players []User `json:"users"` } type PlayerResponse struct { Player User `json:"player"` } type CreatePlayerRequest struct { Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Role string `json:"role" binding:"required,oneof=player organizer"` } type UpdatePlayerRequest struct { Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Role string `json:"role" binding:"required,oneof=player organizer"` Teams []Team `json:"teams"` // Teams the player is part of } type DeletePlayerRequest struct { ID string `json:"id" binding:"required"` } type PlayerService interface { CreatePlayer(req CreatePlayerRequest) (User, error) GetPlayer(id string) (User, error) UpdatePlayer(id string, req UpdatePlayerRequest) (User, error) DeletePlayer(id string) error ListPlayers() ([]User, error) GetPlayerTeams(id string) ([]Team, error) GetPlayerByEmail(email string) (User, error) GetPlayerByName(name string) (User, error) GetPlayerByID(id string) (User, error) GetPlayerByRole(role string) ([]User, error) GetPlayerByTeam(teamID string) ([]User, error) GetPlayerByTournament(tournamentID string) ([]User, error) GetPlayerByOrganizer(organizerID string) ([]User, error) } func LoginPlayer(db *sql.DB, email, password string) (User, error) { var player User var playerPassword string err := db.QueryRow("SELECT id, name, email, password FROM users WHERE email = $1", email).Scan(&player.UUID, &player.Username, &player.Email, playerPassword) if err != nil { log.Printf("Error logging in player with email %s: %v", email, err) return User{}, err } if player.UUID == "" { log.Printf("User with email %s not found", email) return User{}, sql.ErrNoRows // or a custom error } // Check if the password matches if password == playerPassword { log.Printf("User %s logged in successfully", player.Username) } log.Printf("User %s logged in successfully", player.Username) return player, nil } func GetPlayerRole(db *sql.DB, playerID string) ([]string, error) { var role []string var tmp string err := db.QueryRow("SELECT role FROM roles WHERE player_id = $1", playerID).Scan(&tmp) log.Println(tmp) role = strings.Split(tmp, ",") if err != nil { log.Printf("Error retrieving role for player ID %s: %v", playerID, err) return nil, err } if len(role) == 0 { log.Printf("No role found for player ID %s", playerID) return nil, sql.ErrNoRows // or a custom error } log.Printf("Retrieved role for player ID %s: %s", playerID, role) return role, nil } func savePlayer(db *sql.DB, player User) error { // Ensure the player ID is set if player.UUID == "" { player.UUID = uuid.New().String() // Generate a new UUID if not set log.Printf("Generated new player ID: %s", player.UUID) } // Insert the player into the database if len(player.Role) == 0 { player.Role = append(player.Role, "player") // Default role if not specified log.Printf("Setting default role for player %s to 'player'", player.Username) } log.Printf("Saving player: ID=%v, Name=%v, Email=%v", player.UUID, player.Username, player.Email) stmt := "INSERT INTO public.users (UUID, username, email,password_hash) VALUES ($1, $2, $3,$4)" log.Printf("Generated SQL statement: %s", stmt) _, err := db.Exec(stmt, player.UUID, player.Username, player.Email, player.password) if err != nil { log.Printf("Error saving player to database: %v", err) } // lastID, err := res.LastInsertId() // if err != nil { // log.Printf("Error getting last insert ID: %v", err) // } else { // log.Printf("Last insert ID: %d", lastID) // } // if err := db.QueryRow("SELECT id, name, email FROM users WHERE id = ?", player.ID).Scan(&player.ID, &player.Name, &player.Email, &player.Role); err != nil { // log.Printf("Error retrieving player from database: %v", err) // return err // } log.Printf("User %s saved to database", player.Username) return nil } func AddRoleToPlayer(db *sql.DB, playerID string, role []string) error { if playerID == "" { log.Printf("User ID is required to add a role, but got empty ID") return sql.ErrNoRows // or a custom error } log.Printf("Adding role '%s' to player with ID: %s", role, playerID) stmt := "INSERT INTO public.roles (player_id, role) VALUES ($1, $2)" _, err := db.Exec(stmt, playerID, pq.Array(role)) if err != nil { log.Printf("Error adding role to player with ID %s: %v", playerID, err) return err } log.Printf("Role '%s' added to player with ID %s successfully", role, playerID) return nil } func GetAllPlayers(db *sql.DB) ([]User, error) { // rows, err := db.Query("SELECT id, name, email FROM public.users") // rows, err := db.Query("SELECT u.uuid, u.email, u.username, u.firstname,u.lastname,u.birthday, u.is_active, u.created_at, ur.roleFROM public.users u // LEFT JOIN roles ur ON u.uuid::uuid = ur.player_id ORDER BY u.uuid ASC") rows, err := db.Query(getPLayerWithRolesQuery) if err != nil { log.Printf("Error retrieving users: %v", err) return nil, err } defer rows.Close() var users []User for rows.Next() { var player User if err := rows.Scan(&player.UUID, &player.Email, &player.Username, &player.firstname, &player.lastname, &player.birthday, &player.IsActive, &player.Created_at, (*pq.StringArray)(&player.Role), ); err != nil { log.Printf("Error scanning player row: %v", err) return nil, err } users = append(users, player) } if err := rows.Err(); err != nil { log.Printf("Error iterating over player rows: %v", err) return nil, err } return users, nil } func GetPlayerByID(db *sql.DB, id string) (User, error) { var player User err := db.QueryRow("SELECT id, name, email FROM users WHERE id = $1", id).Scan(&player.UUID, &player.Username, &player.Email) if err != nil { log.Printf("Error retrieving player by ID %s: %v", id, err) return User{}, err } return player, nil } func GetPlayerByEmail(db *sql.DB, email string) (User, error) { var player User err := db.QueryRow("SELECT id, name, email FROM users WHERE email = $1", email).Scan(&player.UUID, &player.Username, &player.Email, &player.Role) if err != nil { log.Printf("Error retrieving player by email %s: %v", email, err) return User{}, err } return player, nil } func GetPlayerByName(db *sql.DB, name string) (User, error) { var player User err := db.QueryRow("SELECT id, name, email FROM users WHERE name = $1", name).Scan(&player.UUID, &player.Username, &player.Email, &player.Role) if err != nil { log.Printf("Error retrieving player by name %s: %v", name, err) return User{}, err } return player, nil } // DeletePlayer deletes a player from the database by ID. func deletePlayer(db *sql.DB, uuid string) error { // Delete the player from the database log.Printf("Deleting player with ID: %s", uuid) _, err := db.Exec("DELETE FROM public.users WHERE uuid = $1", uuid) if err != nil { log.Printf("Error deleting player with ID %s: %v", uuid, err) return err } log.Printf("User with ID %s deleted successfully", uuid) return nil } // UpdatePlayer updates an existing player in the database. // It requires the player ID to be set in the User struct. func updatePlayer(db *sql.DB, player User) error { // Ensure the player ID is set if player.UUID == "" { log.Printf("User ID is required for update, but got empty ID") return sql.ErrNoRows // or a custom error } log.Printf("Updating player: ID=%v, Name=%v, Email=%v", player.UUID, player.Username, player.Email) stmt := "UPDATE public.users SET username = $1, email = $2 WHERE uuid = $3" _, err := db.Exec(stmt, player.Username, player.Email, player.UUID) if err != nil { log.Printf("Error updating player in database: %v", err) return err } log.Printf("User %s updated successfully", player.Username) return nil }