package repository

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

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

// QuestionRepository defines the interface for question data operations.
type QuestionRepository interface {
	Create(ctx context.Context, question *models.Question) (*models.Question, error)
	GetByQuizID(ctx context.Context, quizID int) ([]models.Question, error)
	GetByID(ctx context.Context, id int) (*models.Question, error)
	Update(ctx context.Context, id int, question *models.Question) (*models.Question, error)
	Delete(ctx context.Context, id int) error
}

// postgresQuestionRepository implements the QuestionRepository interface.
type postgresQuestionRepository struct {
	db *pgxpool.Pool
}

// NewQuestionRepository creates a new instance of a question repository.
func NewQuestionRepository(db *pgxpool.Pool) QuestionRepository {
	return &postgresQuestionRepository{db: db}
}

// Create inserts a new question into the database.
func (r *postgresQuestionRepository) Create(ctx context.Context, question *models.Question) (*models.Question, error) {
	query := `
		INSERT INTO questions (quiz_id, text, type, options, order_index)
		VALUES ($1, $2, $3, $4, $5)
		RETURNING id
	`
	err := r.db.QueryRow(ctx, query,
		question.QuizID, question.Text, question.Type, question.Options, question.OrderIndex,
	).Scan(&question.ID)

	if err != nil {
		return nil, err
	}

	return question, nil
}

// GetByQuizID retrieves all questions for a given quiz ID.
func (r *postgresQuestionRepository) GetByQuizID(ctx context.Context, quizID int) ([]models.Question, error) {
	query := `
		SELECT id, quiz_id, text, type, options, order_index
		FROM questions
		WHERE quiz_id = $1
		ORDER BY order_index ASC
	`
	rows, err := r.db.Query(ctx, query, quizID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var questions []models.Question
	for rows.Next() {
		var q models.Question
		if err := rows.Scan(&q.ID, &q.QuizID, &q.Text, &q.Type, &q.Options, &q.OrderIndex); err != nil {
			return nil, err
		}
		questions = append(questions, q)
	}

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

	if questions == nil {
		return []models.Question{}, nil
	}

	return questions, nil
}

// GetByID retrieves a single question by its ID.
func (r *postgresQuestionRepository) GetByID(ctx context.Context, id int) (*models.Question, error) {
	query := `
		SELECT id, quiz_id, text, type, options, order_index
		FROM questions
		WHERE id = $1
	`

	var q models.Question
	err := r.db.QueryRow(ctx, query, id).Scan(&q.ID, &q.QuizID, &q.Text, &q.Type, &q.Options, &q.OrderIndex)

	if err != nil {
		return nil, err
	}

	return &q, nil
}

// Update updates an existing question
func (r *postgresQuestionRepository) Update(ctx context.Context, id int, question *models.Question) (*models.Question, error) {
	query := `
		UPDATE questions
		SET text = $2, type = $3, options = $4, order_index = $5
		WHERE id = $1
		RETURNING id, quiz_id, text, type, options, order_index
	`

	var q models.Question
	err := r.db.QueryRow(ctx, query,
		id, question.Text, question.Type, question.Options, question.OrderIndex,
	).Scan(&q.ID, &q.QuizID, &q.Text, &q.Type, &q.Options, &q.OrderIndex)

	if err != nil {
		return nil, err
	}

	return &q, nil
}

// Delete deletes a question
func (r *postgresQuestionRepository) Delete(ctx context.Context, id int) error {
	_, err := r.db.Exec(ctx, "DELETE FROM questions WHERE id = $1", id)
	return err
}
