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
}
