package db

import (
	"errors"
	"fmt"
	"music-server/pkg/models"
	"os"
	"time"

	"github.com/jackc/pgtype"
)

func GetGameName(gameId int) string {
	var gameName = ""
	err := Dbpool.QueryRow(Ctx,
		"SELECT game_name FROM game WHERE id = $1", gameId).Scan(&gameName)
	if err != nil {
		if compareError.Error() != err.Error() {
			_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		}
		return ""
	}
	return gameName
}

func GetGameById(gameId int) (models.GameData, error) {
	var id, timesPlayed int
	var numberOfSongs pgtype.Int4
	var gameName, path string
	var added, deleted, lastChanged, lastPlayed pgtype.Timestamp
	err := Dbpool.QueryRow(Ctx,
		"SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs "+
			"FROM game WHERE id = $1 AND deleted IS NULL ", gameId).Scan(&id, &gameName, &added, &deleted, &lastChanged, &path, &timesPlayed, &lastPlayed, &numberOfSongs)
	if err != nil {
		if compareError.Error() != err.Error() {
			_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		}
		return models.GameData{}, errors.New("Game not found")
	}
	return models.GameData{
		Id:            id,
		GameName:      gameName,
		Added:         added.Time,
		Deleted:       deleted.Time,
		LastChanged:   lastChanged.Time,
		Path:          path,
		TimesPlayed:   timesPlayed,
		LastPlayed:    lastPlayed.Time,
		NumberOfSongs: numberOfSongs.Int,
	}, nil
}

func SetGameDeletionDate() {
	_, err := Dbpool.Exec(Ctx,
		"UPDATE game SET deleted=$1 WHERE deleted IS NULL", time.Now())
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
	}
}

func ClearGames() {
	_, err := Dbpool.Exec(Ctx, "DELETE FROM game")
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
	}
}

func UpdateGameName(id int, name string, path string) {
	_, err := Dbpool.Exec(Ctx,
		"UPDATE game SET game_name=$1, path=$2, last_changed=$3 WHERE id=$4",
		name, path, time.Now(), id)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
	}
}

func RemoveDeletionDate(id int) {
	_, err := Dbpool.Exec(Ctx,
		"UPDATE game SET deleted=null WHERE id=$1", id)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
	}
}

func GetIdByGameName(name string) int {
	var gameId = -1
	err := Dbpool.QueryRow(Ctx,
		"SELECT id FROM game WHERE game_name = $1", name).Scan(&gameId)
	if err != nil {
		if compareError.Error() != err.Error() {
			_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		}
		return -1
	}
	return gameId
}

func InsertGame(name string, path string) int {
	gameId := -1
	err := Dbpool.QueryRow(Ctx,
		"INSERT INTO game(game_name, path, added) VALUES ($1, $2, $3) RETURNING id",
		name, path, time.Now()).Scan(&gameId)
	if err != nil {
		if compareError.Error() != err.Error() {
			_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		}
		resetGameIdSeq()
		err2 := Dbpool.QueryRow(Ctx,
			"INSERT INTO game(game_name, path, added) VALUES ($1, $2, $3) RETURNING id",
			name, path, time.Now()).Scan(&gameId)
		if err2 != nil {
			if compareError.Error() != err2.Error() {
				_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
			}
			return -1
		}
	}
	return gameId
}

func InsertGameWithExistingId(id int, name string, path string) {
	_, err := Dbpool.Exec(Ctx,
		"INSERT INTO game(id, game_name, path, added) VALUES ($1, $2, $3, $4)",
		id, name, path, time.Now())
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
	}
}

func FindAllGames() []models.GameData {
	rows, err := Dbpool.Query(Ctx,
		"SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs "+
			"FROM game WHERE deleted IS NULL "+
			"ORDER BY game_name")
	if err != nil {
		if compareError.Error() != err.Error() {
			_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		}
	}
	var gameList []models.GameData
	for rows.Next() {
		var id, timesPlayed int
		var numberOfSongs pgtype.Int4
		var gameName, path string
		var added, deleted, lastChanged, lastPlayed pgtype.Timestamp
		err := rows.Scan(&id, &gameName, &added, &deleted, &lastChanged, &path, &timesPlayed, &lastPlayed, &numberOfSongs)
		if err != nil {
			if compareError.Error() != err.Error() {
				_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
			}
		}
		gameList = append(gameList, models.GameData{
			Id:            id,
			GameName:      gameName,
			Added:         added.Time,
			Deleted:       deleted.Time,
			LastChanged:   lastChanged.Time,
			Path:          path,
			TimesPlayed:   timesPlayed,
			LastPlayed:    lastPlayed.Time,
			NumberOfSongs: numberOfSongs.Int,
		})
	}
	return gameList
}

func AddGamePlayed(id int) {
	_, err := Dbpool.Exec(Ctx,
		"UPDATE game SET times_played=times_played+1, last_played=now() WHERE id=$1", id)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
	}
}
