package repository

import (
	"context"
	"sno/internal/models"

	"github.com/jackc/pgx/v5/pgxpool"
)

// UserRepository defines the interface for user data operations.
type UserRepository interface {
	GetByID(ctx context.Context, telegramID int64) (*models.User, error)
	CreateUser(ctx context.Context, user *models.User) error
	UpdateStarsBalance(ctx context.Context, userID int64, amount int) error
	GetDB() *pgxpool.Pool
}

// postgresUserRepository implements the UserRepository interface.
type postgresUserRepository struct {
	db *pgxpool.Pool
}

// NewUserRepository creates a new instance of a user repository.
func NewUserRepository(db *pgxpool.Pool) UserRepository {
	return &postgresUserRepository{db: db}
}

// GetByID retrieves a single user by their Telegram ID.
func (r *postgresUserRepository) GetByID(ctx context.Context, telegramID int64) (*models.User, error) {
	query := `SELECT telegram_id, username, first_name, last_name, photo_url, stars_balance, created_at FROM users WHERE telegram_id = $1`
	var u models.User
	err := r.db.QueryRow(ctx, query, telegramID).Scan(
		&u.TelegramID, &u.Username, &u.FirstName, &u.LastName, &u.PhotoURL, &u.StarsBalance, &u.CreatedAt,
	)
	if err != nil {
		return nil, err
	}
	return &u, nil
}

// UpdateStarsBalance adds (or removes, if negative) a certain amount of stars to the user's balance.
func (r *postgresUserRepository) UpdateStarsBalance(ctx context.Context, userID int64, amount int) error {
	query := `UPDATE users SET stars_balance = stars_balance + $1 WHERE telegram_id = $2`
	querier := getQuerier(ctx, r.db)
	_, err := querier.Exec(ctx, query, amount, userID)
	return err
}

// CreateUser creates a new user in the database
func (r *postgresUserRepository) CreateUser(ctx context.Context, user *models.User) error {
	query := `INSERT INTO users (telegram_id, username, first_name, last_name, photo_url, stars_balance) VALUES ($1, $2, $3, $4, $5, $6)`
	querier := getQuerier(ctx, r.db)
	_, err := querier.Exec(ctx, query, user.TelegramID, user.Username, user.FirstName, user.LastName, user.PhotoURL, user.StarsBalance)
	return err
}

// GetDB returns the database connection pool
func (r *postgresUserRepository) GetDB() *pgxpool.Pool {
	return r.db
}