package repository

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

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

// QuizAttemptRepository defines the interface for quiz attempt data operations.
type QuizAttemptRepository interface {
	Create(ctx context.Context, attempt *models.QuizAttempt) (*models.QuizAttempt, error)
	GetLatestByUserIDAndQuizID(ctx context.Context, userID int64, quizID int) (*models.QuizAttempt, error)
	GetByUserID(ctx context.Context, userID int64) ([]models.QuizAttempt, error)
}

// postgresQuizAttemptRepository implements the QuizAttemptRepository interface.
type postgresQuizAttemptRepository struct {
	db *pgxpool.Pool
}

// NewQuizAttemptRepository creates a new instance of a quiz attempt repository.
func NewQuizAttemptRepository(db *pgxpool.Pool) QuizAttemptRepository {
	return &postgresQuizAttemptRepository{db: db}
}

// Create inserts a new quiz attempt record into the database.
func (r *postgresQuizAttemptRepository) Create(ctx context.Context, attempt *models.QuizAttempt) (*models.QuizAttempt, error) {
	query := `
		INSERT INTO quiz_attempts (user_id, quiz_id, score, stars_earned, answers)
		VALUES ($1, $2, $3, $4, $5)
		RETURNING id, completed_at
	`
	querier := getQuerier(ctx, r.db)
	err := querier.QueryRow(ctx, query,
		attempt.UserID, attempt.QuizID, attempt.Score, attempt.StarsEarned, attempt.Answers,
	).Scan(&attempt.ID, &attempt.CompletedAt)

	if err != nil {
		return nil, err
	}

	return attempt, nil
}

// GetLatestByUserIDAndQuizID retrieves the most recent quiz attempt for a given user and quiz.
func (r *postgresQuizAttemptRepository) GetLatestByUserIDAndQuizID(ctx context.Context, userID int64, quizID int) (*models.QuizAttempt, error) {
	query := `
		SELECT id, user_id, quiz_id, score, stars_earned, completed_at, answers
		FROM quiz_attempts
		WHERE user_id = $1 AND quiz_id = $2
		ORDER BY completed_at DESC
		LIMIT 1
	`
	var attempt models.QuizAttempt
	err := r.db.QueryRow(ctx, query, userID, quizID).Scan(
		&attempt.ID, &attempt.UserID, &attempt.QuizID, &attempt.Score, &attempt.StarsEarned, &attempt.CompletedAt, &attempt.Answers,
	)
	if err != nil {
		return nil, err // pgx.ErrNoRows is a common error here, handled by the service
	}
	return &attempt, nil
}

// GetByUserID retrieves all quiz attempts for a given user.
func (r *postgresQuizAttemptRepository) GetByUserID(ctx context.Context, userID int64) ([]models.QuizAttempt, error) {
	query := `
		SELECT id, user_id, quiz_id, score, stars_earned, completed_at, answers
		FROM quiz_attempts
		WHERE user_id = $1
		ORDER BY completed_at DESC
	`
	rows, err := r.db.Query(ctx, query, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var attempts []models.QuizAttempt
	for rows.Next() {
		var a models.QuizAttempt
		if err := rows.Scan(&a.ID, &a.UserID, &a.QuizID, &a.Score, &a.StarsEarned, &a.CompletedAt, &a.Answers); err != nil {
			return nil, err
		}
		attempts = append(attempts, a)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	if attempts == nil {
		return []models.QuizAttempt{}, nil
	}

	return attempts, nil
}
