package repository

import (
	"context"
	"time"

	dbgen "Yimaru-Backend/gen/db"
	"Yimaru-Backend/internal/domain"

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

func toPgText(s *string) pgtype.Text {
	if s == nil {
		return pgtype.Text{Valid: false}
	}
	return pgtype.Text{String: *s, Valid: true}
}

func fromPgText(t pgtype.Text) *string {
	if !t.Valid {
		return nil
	}
	return &t.String
}

func fromPgInt4(i pgtype.Int4) *int32 {
	if !i.Valid {
		return nil
	}
	return &i.Int32
}

func fromPgInt8(i pgtype.Int8) *int64 {
	if !i.Valid {
		return nil
	}
	return &i.Int64
}

func toPgInt4(i *int32) pgtype.Int4 {
	if i == nil {
		return pgtype.Int4{Valid: false}
	}
	return pgtype.Int4{Int32: *i, Valid: true}
}

func toPgInt8(i *int64) pgtype.Int8 {
	if i == nil {
		return pgtype.Int8{Valid: false}
	}
	return pgtype.Int8{Int64: *i, Valid: true}
}

func timePtr(t pgtype.Timestamptz) *time.Time {
	if !t.Valid {
		return nil
	}
	return &t.Time
}

func questionToDomain(q dbgen.Question) domain.Question {
	return domain.Question{
		ID:                      q.ID,
		QuestionText:            q.QuestionText,
		QuestionType:            q.QuestionType,
		DifficultyLevel:         fromPgText(q.DifficultyLevel),
		Points:                  q.Points,
		Explanation:             fromPgText(q.Explanation),
		Tips:                    fromPgText(q.Tips),
		VoicePrompt:             fromPgText(q.VoicePrompt),
		SampleAnswerVoicePrompt: fromPgText(q.SampleAnswerVoicePrompt),
		Status:                  q.Status,
		CreatedAt:               q.CreatedAt.Time,
		UpdatedAt:               timePtr(q.UpdatedAt),
	}
}

func questionOptionToDomain(o dbgen.QuestionOption) domain.QuestionOption {
	return domain.QuestionOption{
		ID:          o.ID,
		QuestionID:  o.QuestionID,
		OptionText:  o.OptionText,
		OptionOrder: o.OptionOrder,
		IsCorrect:   o.IsCorrect,
		CreatedAt:   o.CreatedAt.Time,
	}
}

func questionShortAnswerToDomain(a dbgen.QuestionShortAnswer) domain.QuestionShortAnswer {
	return domain.QuestionShortAnswer{
		ID:               a.ID,
		QuestionID:       a.QuestionID,
		AcceptableAnswer: a.AcceptableAnswer,
		MatchType:        a.MatchType,
		CreatedAt:        a.CreatedAt.Time,
	}
}

func questionSetToDomain(qs dbgen.QuestionSet) domain.QuestionSet {
	return domain.QuestionSet{
		ID:               qs.ID,
		Title:            qs.Title,
		Description:      fromPgText(qs.Description),
		SetType:          qs.SetType,
		OwnerType:        fromPgText(qs.OwnerType),
		OwnerID:          fromPgInt8(qs.OwnerID),
		BannerImage:      fromPgText(qs.BannerImage),
		Persona:          fromPgText(qs.Persona),
		TimeLimitMinutes: fromPgInt4(qs.TimeLimitMinutes),
		PassingScore:     fromPgInt4(qs.PassingScore),
		ShuffleQuestions: qs.ShuffleQuestions,
		Status:           qs.Status,
		SubCourseVideoID: fromPgInt8(qs.SubCourseVideoID),
		CreatedAt:        qs.CreatedAt.Time,
		UpdatedAt:        timePtr(qs.UpdatedAt),
	}
}

func questionSetItemToDomain(i dbgen.QuestionSetItem) domain.QuestionSetItem {
	return domain.QuestionSetItem{
		ID:           i.ID,
		SetID:        i.SetID,
		QuestionID:   i.QuestionID,
		DisplayOrder: i.DisplayOrder,
		CreatedAt:    i.CreatedAt.Time,
	}
}

func (s *Store) CreateQuestion(ctx context.Context, input domain.CreateQuestionInput) (domain.Question, error) {
	q, tx, err := s.BeginTx(ctx)
	if err != nil {
		return domain.Question{}, err
	}
	defer tx.Rollback(ctx)

	var points interface{}
	if input.Points != nil {
		points = *input.Points
	}
	var status interface{}
	if input.Status != nil {
		status = *input.Status
	}

	question, err := q.CreateQuestion(ctx, dbgen.CreateQuestionParams{
		QuestionText:            input.QuestionText,
		QuestionType:            input.QuestionType,
		DifficultyLevel:         toPgText(input.DifficultyLevel),
		Column4:                 points,
		Explanation:             toPgText(input.Explanation),
		Tips:                    toPgText(input.Tips),
		VoicePrompt:             toPgText(input.VoicePrompt),
		SampleAnswerVoicePrompt: toPgText(input.SampleAnswerVoicePrompt),
		Column9:                 status,
	})
	if err != nil {
		return domain.Question{}, err
	}

	for _, opt := range input.Options {
		var order interface{}
		if opt.OptionOrder != nil {
			order = *opt.OptionOrder
		}
		_, err = q.CreateQuestionOption(ctx, dbgen.CreateQuestionOptionParams{
			QuestionID: question.ID,
			OptionText: opt.OptionText,
			Column3:    order,
			Column4:    opt.IsCorrect,
		})
		if err != nil {
			return domain.Question{}, err
		}
	}

	for _, sa := range input.ShortAnswers {
		var matchType interface{}
		if sa.MatchType != nil {
			matchType = *sa.MatchType
		}
		_, err = q.CreateQuestionShortAnswer(ctx, dbgen.CreateQuestionShortAnswerParams{
			QuestionID:       question.ID,
			AcceptableAnswer: sa.AcceptableAnswer,
			Column3:          matchType,
		})
		if err != nil {
			return domain.Question{}, err
		}
	}

	if err = tx.Commit(ctx); err != nil {
		return domain.Question{}, err
	}

	return questionToDomain(question), nil
}

func (s *Store) GetQuestionByID(ctx context.Context, id int64) (domain.Question, error) {
	q, err := s.queries.GetQuestionByID(ctx, id)
	if err != nil {
		return domain.Question{}, err
	}
	return questionToDomain(q), nil
}

func (s *Store) GetQuestionWithDetails(ctx context.Context, id int64) (domain.QuestionWithDetails, error) {
	q, err := s.queries.GetQuestionByID(ctx, id)
	if err != nil {
		return domain.QuestionWithDetails{}, err
	}

	opts, err := s.queries.GetOptionsByQuestionID(ctx, id)
	if err != nil {
		return domain.QuestionWithDetails{}, err
	}

	shortAnswers, err := s.queries.GetShortAnswersByQuestionID(ctx, id)
	if err != nil {
		return domain.QuestionWithDetails{}, err
	}

	options := make([]domain.QuestionOption, len(opts))
	for i, o := range opts {
		options[i] = questionOptionToDomain(o)
	}

	answers := make([]domain.QuestionShortAnswer, len(shortAnswers))
	for i, a := range shortAnswers {
		answers[i] = questionShortAnswerToDomain(a)
	}

	return domain.QuestionWithDetails{
		Question:     questionToDomain(q),
		Options:      options,
		ShortAnswers: answers,
	}, nil
}

func (s *Store) ListQuestions(ctx context.Context, questionType, difficulty, status *string, limit, offset int32) ([]domain.Question, int64, error) {
	var qType, diff, stat string
	if questionType != nil {
		qType = *questionType
	}
	if difficulty != nil {
		diff = *difficulty
	}
	if status != nil {
		stat = *status
	}

	rows, err := s.queries.ListQuestions(ctx, dbgen.ListQuestionsParams{
		Column1: qType,
		Column2: diff,
		Column3: stat,
		Limit:   pgtype.Int4{Int32: limit, Valid: true},
		Offset:  pgtype.Int4{Int32: offset, Valid: true},
	})
	if err != nil {
		return nil, 0, err
	}

	var totalCount int64
	questions := make([]domain.Question, len(rows))
	for i, r := range rows {
		if i == 0 {
			totalCount = r.TotalCount
		}
		questions[i] = domain.Question{
			ID:                      r.ID,
			QuestionText:            r.QuestionText,
			QuestionType:            r.QuestionType,
			DifficultyLevel:         fromPgText(r.DifficultyLevel),
			Points:                  r.Points,
			Explanation:             fromPgText(r.Explanation),
			Tips:                    fromPgText(r.Tips),
			VoicePrompt:             fromPgText(r.VoicePrompt),
			SampleAnswerVoicePrompt: fromPgText(r.SampleAnswerVoicePrompt),
			Status:                  r.Status,
			CreatedAt:               r.CreatedAt.Time,
			UpdatedAt:               timePtr(r.UpdatedAt),
		}
	}

	return questions, totalCount, nil
}

func (s *Store) SearchQuestions(ctx context.Context, query string, limit, offset int32) ([]domain.Question, int64, error) {
	rows, err := s.queries.SearchQuestions(ctx, dbgen.SearchQuestionsParams{
		Column1: pgtype.Text{String: query, Valid: true},
		Limit:   pgtype.Int4{Int32: limit, Valid: true},
		Offset:  pgtype.Int4{Int32: offset, Valid: true},
	})
	if err != nil {
		return nil, 0, err
	}

	var totalCount int64
	questions := make([]domain.Question, len(rows))
	for i, r := range rows {
		if i == 0 {
			totalCount = r.TotalCount
		}
		questions[i] = domain.Question{
			ID:                      r.ID,
			QuestionText:            r.QuestionText,
			QuestionType:            r.QuestionType,
			DifficultyLevel:         fromPgText(r.DifficultyLevel),
			Points:                  r.Points,
			Explanation:             fromPgText(r.Explanation),
			Tips:                    fromPgText(r.Tips),
			VoicePrompt:             fromPgText(r.VoicePrompt),
			SampleAnswerVoicePrompt: fromPgText(r.SampleAnswerVoicePrompt),
			Status:                  r.Status,
			CreatedAt:               r.CreatedAt.Time,
			UpdatedAt:               timePtr(r.UpdatedAt),
		}
	}

	return questions, totalCount, nil
}

func (s *Store) UpdateQuestion(ctx context.Context, id int64, input domain.CreateQuestionInput) error {
	var points int32
	if input.Points != nil {
		points = *input.Points
	}
	var status string
	if input.Status != nil {
		status = *input.Status
	}

	return s.queries.UpdateQuestion(ctx, dbgen.UpdateQuestionParams{
		ID:                      id,
		QuestionText:            input.QuestionText,
		QuestionType:            input.QuestionType,
		DifficultyLevel:         toPgText(input.DifficultyLevel),
		Points:                  points,
		Explanation:             toPgText(input.Explanation),
		Tips:                    toPgText(input.Tips),
		VoicePrompt:             toPgText(input.VoicePrompt),
		SampleAnswerVoicePrompt: toPgText(input.SampleAnswerVoicePrompt),
		Status:                  status,
	})
}

func (s *Store) ArchiveQuestion(ctx context.Context, id int64) error {
	return s.queries.ArchiveQuestion(ctx, id)
}

func (s *Store) DeleteQuestion(ctx context.Context, id int64) error {
	return s.queries.DeleteQuestion(ctx, id)
}

func (s *Store) CreateQuestionOption(ctx context.Context, questionID int64, optionText string, optionOrder *int32, isCorrect bool) (domain.QuestionOption, error) {
	var order interface{}
	if optionOrder != nil {
		order = *optionOrder
	}

	opt, err := s.queries.CreateQuestionOption(ctx, dbgen.CreateQuestionOptionParams{
		QuestionID: questionID,
		OptionText: optionText,
		Column3:    order,
		Column4:    isCorrect,
	})
	if err != nil {
		return domain.QuestionOption{}, err
	}
	return questionOptionToDomain(opt), nil
}

func (s *Store) GetOptionsByQuestionID(ctx context.Context, questionID int64) ([]domain.QuestionOption, error) {
	opts, err := s.queries.GetOptionsByQuestionID(ctx, questionID)
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionOption, len(opts))
	for i, o := range opts {
		result[i] = questionOptionToDomain(o)
	}
	return result, nil
}

func (s *Store) UpdateQuestionOption(ctx context.Context, id int64, optionText *string, optionOrder *int32, isCorrect *bool) error {
	var text string
	if optionText != nil {
		text = *optionText
	}
	var order int32
	if optionOrder != nil {
		order = *optionOrder
	}
	var correct bool
	if isCorrect != nil {
		correct = *isCorrect
	}

	return s.queries.UpdateQuestionOption(ctx, dbgen.UpdateQuestionOptionParams{
		ID:          id,
		OptionText:  text,
		OptionOrder: order,
		IsCorrect:   correct,
	})
}

func (s *Store) DeleteQuestionOption(ctx context.Context, id int64) error {
	return s.queries.DeleteQuestionOption(ctx, id)
}

func (s *Store) DeleteOptionsByQuestionID(ctx context.Context, questionID int64) error {
	return s.queries.DeleteOptionsByQuestionID(ctx, questionID)
}

func (s *Store) CreateQuestionShortAnswer(ctx context.Context, questionID int64, acceptableAnswer string, matchType *string) (domain.QuestionShortAnswer, error) {
	var mt interface{}
	if matchType != nil {
		mt = *matchType
	}

	sa, err := s.queries.CreateQuestionShortAnswer(ctx, dbgen.CreateQuestionShortAnswerParams{
		QuestionID:       questionID,
		AcceptableAnswer: acceptableAnswer,
		Column3:          mt,
	})
	if err != nil {
		return domain.QuestionShortAnswer{}, err
	}
	return questionShortAnswerToDomain(sa), nil
}

func (s *Store) GetShortAnswersByQuestionID(ctx context.Context, questionID int64) ([]domain.QuestionShortAnswer, error) {
	answers, err := s.queries.GetShortAnswersByQuestionID(ctx, questionID)
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionShortAnswer, len(answers))
	for i, a := range answers {
		result[i] = questionShortAnswerToDomain(a)
	}
	return result, nil
}

func (s *Store) UpdateQuestionShortAnswer(ctx context.Context, id int64, acceptableAnswer, matchType *string) error {
	var answer, mt string
	if acceptableAnswer != nil {
		answer = *acceptableAnswer
	}
	if matchType != nil {
		mt = *matchType
	}

	return s.queries.UpdateQuestionShortAnswer(ctx, dbgen.UpdateQuestionShortAnswerParams{
		ID:               id,
		AcceptableAnswer: answer,
		MatchType:        mt,
	})
}

func (s *Store) DeleteQuestionShortAnswer(ctx context.Context, id int64) error {
	return s.queries.DeleteQuestionShortAnswer(ctx, id)
}

func (s *Store) DeleteShortAnswersByQuestionID(ctx context.Context, questionID int64) error {
	return s.queries.DeleteShortAnswersByQuestionID(ctx, questionID)
}

func (s *Store) CreateQuestionSet(ctx context.Context, input domain.CreateQuestionSetInput) (domain.QuestionSet, error) {
	var shuffleQuestions interface{}
	if input.ShuffleQuestions != nil {
		shuffleQuestions = *input.ShuffleQuestions
	}
	var status interface{}
	if input.Status != nil {
		status = *input.Status
	}

	qs, err := s.queries.CreateQuestionSet(ctx, dbgen.CreateQuestionSetParams{
		Title:            input.Title,
		Description:      toPgText(input.Description),
		SetType:          input.SetType,
		OwnerType:        toPgText(input.OwnerType),
		OwnerID:          toPgInt8(input.OwnerID),
		BannerImage:      toPgText(input.BannerImage),
		Persona:          toPgText(input.Persona),
		TimeLimitMinutes: toPgInt4(input.TimeLimitMinutes),
		PassingScore:     toPgInt4(input.PassingScore),
		Column10:         shuffleQuestions,
		Column11:         status,
		SubCourseVideoID: toPgInt8(input.SubCourseVideoID),
	})
	if err != nil {
		return domain.QuestionSet{}, err
	}
	return questionSetToDomain(qs), nil
}

func (s *Store) GetQuestionSetByID(ctx context.Context, id int64) (domain.QuestionSet, error) {
	qs, err := s.queries.GetQuestionSetByID(ctx, id)
	if err != nil {
		return domain.QuestionSet{}, err
	}
	return questionSetToDomain(qs), nil
}

func (s *Store) GetQuestionSetsByOwner(ctx context.Context, ownerType string, ownerID int64) ([]domain.QuestionSet, error) {
	sets, err := s.queries.GetQuestionSetsByOwner(ctx, dbgen.GetQuestionSetsByOwnerParams{
		OwnerType: pgtype.Text{String: ownerType, Valid: true},
		OwnerID:   pgtype.Int8{Int64: ownerID, Valid: true},
	})
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionSet, len(sets))
	for i, qs := range sets {
		result[i] = questionSetToDomain(qs)
	}
	return result, nil
}

func (s *Store) GetQuestionSetsByType(ctx context.Context, setType string, limit, offset int32) ([]domain.QuestionSet, int64, error) {
	rows, err := s.queries.GetQuestionSetsByType(ctx, dbgen.GetQuestionSetsByTypeParams{
		SetType: setType,
		Limit:   pgtype.Int4{Int32: limit, Valid: true},
		Offset:  pgtype.Int4{Int32: offset, Valid: true},
	})
	if err != nil {
		return nil, 0, err
	}

	var totalCount int64
	result := make([]domain.QuestionSet, len(rows))
	for i, r := range rows {
		if i == 0 {
			totalCount = r.TotalCount
		}
		result[i] = domain.QuestionSet{
			ID:               r.ID,
			Title:            r.Title,
			Description:      fromPgText(r.Description),
			SetType:          r.SetType,
			OwnerType:        fromPgText(r.OwnerType),
			OwnerID:          fromPgInt8(r.OwnerID),
			BannerImage:      fromPgText(r.BannerImage),
			Persona:          fromPgText(r.Persona),
			TimeLimitMinutes: fromPgInt4(r.TimeLimitMinutes),
			PassingScore:     fromPgInt4(r.PassingScore),
			ShuffleQuestions: r.ShuffleQuestions,
			Status:           r.Status,
			SubCourseVideoID: fromPgInt8(r.SubCourseVideoID),
			CreatedAt:        r.CreatedAt.Time,
			UpdatedAt:        timePtr(r.UpdatedAt),
		}
	}
	return result, totalCount, nil
}

func (s *Store) GetPublishedQuestionSetsByOwner(ctx context.Context, ownerType string, ownerID int64) ([]domain.QuestionSet, error) {
	sets, err := s.queries.GetPublishedQuestionSetsByOwner(ctx, dbgen.GetPublishedQuestionSetsByOwnerParams{
		OwnerType: pgtype.Text{String: ownerType, Valid: true},
		OwnerID:   pgtype.Int8{Int64: ownerID, Valid: true},
	})
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionSet, len(sets))
	for i, qs := range sets {
		result[i] = questionSetToDomain(qs)
	}
	return result, nil
}

func (s *Store) GetInitialAssessmentSet(ctx context.Context) (domain.QuestionSet, error) {
	qs, err := s.queries.GetInitialAssessmentSet(ctx)
	if err != nil {
		return domain.QuestionSet{}, err
	}
	return questionSetToDomain(qs), nil
}

func (s *Store) UpdateQuestionSet(ctx context.Context, id int64, input domain.CreateQuestionSetInput) error {
	var shuffleQuestions bool
	if input.ShuffleQuestions != nil {
		shuffleQuestions = *input.ShuffleQuestions
	}
	var status string
	if input.Status != nil {
		status = *input.Status
	}

	return s.queries.UpdateQuestionSet(ctx, dbgen.UpdateQuestionSetParams{
		ID:               id,
		Title:            input.Title,
		Description:      toPgText(input.Description),
		BannerImage:      toPgText(input.BannerImage),
		Persona:          toPgText(input.Persona),
		TimeLimitMinutes: toPgInt4(input.TimeLimitMinutes),
		PassingScore:     toPgInt4(input.PassingScore),
		ShuffleQuestions: shuffleQuestions,
		Status:           status,
		SubCourseVideoID: toPgInt8(input.SubCourseVideoID),
	})
}

func (s *Store) ArchiveQuestionSet(ctx context.Context, id int64) error {
	return s.queries.ArchiveQuestionSet(ctx, id)
}

func (s *Store) DeleteQuestionSet(ctx context.Context, id int64) error {
	return s.queries.DeleteQuestionSet(ctx, id)
}

func (s *Store) AddQuestionToSet(ctx context.Context, setID, questionID int64, displayOrder *int32) (domain.QuestionSetItem, error) {
	var order interface{}
	if displayOrder != nil {
		order = *displayOrder
	}

	item, err := s.queries.AddQuestionToSet(ctx, dbgen.AddQuestionToSetParams{
		SetID:      setID,
		QuestionID: questionID,
		Column3:    order,
	})
	if err != nil {
		return domain.QuestionSetItem{}, err
	}
	return questionSetItemToDomain(item), nil
}

func (s *Store) GetQuestionSetItems(ctx context.Context, setID int64) ([]domain.QuestionSetItemWithQuestion, error) {
	rows, err := s.queries.GetQuestionSetItems(ctx, setID)
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionSetItemWithQuestion, len(rows))
	for i, r := range rows {
		result[i] = domain.QuestionSetItemWithQuestion{
			QuestionSetItem: domain.QuestionSetItem{
				ID:           r.ID,
				SetID:        r.SetID,
				QuestionID:   r.QuestionID,
				DisplayOrder: r.DisplayOrder,
			},
			QuestionText:    r.QuestionText,
			QuestionType:    r.QuestionType,
			DifficultyLevel: fromPgText(r.DifficultyLevel),
			Points:          r.Points,
			Explanation:     fromPgText(r.Explanation),
			Tips:            fromPgText(r.Tips),
			VoicePrompt:     fromPgText(r.VoicePrompt),
			QuestionStatus:  r.QuestionStatus,
		}
	}
	return result, nil
}

func (s *Store) GetPublishedQuestionsInSet(ctx context.Context, setID int64) ([]domain.QuestionSetItemWithQuestion, error) {
	rows, err := s.queries.GetPublishedQuestionsInSet(ctx, setID)
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionSetItemWithQuestion, len(rows))
	for i, r := range rows {
		result[i] = domain.QuestionSetItemWithQuestion{
			QuestionSetItem: domain.QuestionSetItem{
				ID:           r.ID,
				SetID:        r.SetID,
				QuestionID:   r.QuestionID,
				DisplayOrder: r.DisplayOrder,
			},
			QuestionText:    r.QuestionText,
			QuestionType:    r.QuestionType,
			DifficultyLevel: fromPgText(r.DifficultyLevel),
			Points:          r.Points,
			Explanation:     fromPgText(r.Explanation),
			Tips:            fromPgText(r.Tips),
			VoicePrompt:     fromPgText(r.VoicePrompt),
			QuestionStatus:  "PUBLISHED",
		}
	}
	return result, nil
}

func (s *Store) RemoveQuestionFromSet(ctx context.Context, setID, questionID int64) error {
	return s.queries.RemoveQuestionFromSet(ctx, dbgen.RemoveQuestionFromSetParams{
		SetID:      setID,
		QuestionID: questionID,
	})
}

func (s *Store) UpdateQuestionOrder(ctx context.Context, setID, questionID int64, displayOrder int32) error {
	return s.queries.UpdateQuestionOrder(ctx, dbgen.UpdateQuestionOrderParams{
		SetID:        setID,
		QuestionID:   questionID,
		DisplayOrder: displayOrder,
	})
}

func (s *Store) CountQuestionsInSet(ctx context.Context, setID int64) (int64, error) {
	return s.queries.CountQuestionsInSet(ctx, setID)
}

func (s *Store) GetQuestionSetsContainingQuestion(ctx context.Context, questionID int64) ([]domain.QuestionSet, error) {
	sets, err := s.queries.GetQuestionSetsContainingQuestion(ctx, questionID)
	if err != nil {
		return nil, err
	}

	result := make([]domain.QuestionSet, len(sets))
	for i, qs := range sets {
		result[i] = questionSetToDomain(qs)
	}
	return result, nil
}

// User Persona methods for question sets

func (s *Store) AddUserPersonaToQuestionSet(ctx context.Context, questionSetID, userID int64, displayOrder int32) error {
	_, err := s.queries.AddUserPersonaToQuestionSet(ctx, dbgen.AddUserPersonaToQuestionSetParams{
		QuestionSetID: questionSetID,
		UserID:        userID,
		Column3:       displayOrder,
	})
	return err
}

func (s *Store) RemoveUserPersonaFromQuestionSet(ctx context.Context, questionSetID, userID int64) error {
	return s.queries.RemoveUserPersonaFromQuestionSet(ctx, dbgen.RemoveUserPersonaFromQuestionSetParams{
		QuestionSetID: questionSetID,
		UserID:        userID,
	})
}

func (s *Store) GetUserPersonasByQuestionSetID(ctx context.Context, questionSetID int64) ([]domain.UserPersona, error) {
	rows, err := s.queries.GetUserPersonasByQuestionSetID(ctx, questionSetID)
	if err != nil {
		return nil, err
	}

	result := make([]domain.UserPersona, len(rows))
	for i, r := range rows {
		result[i] = domain.UserPersona{
			ID:                r.ID,
			FirstName:         fromPgText(r.FirstName),
			LastName:          fromPgText(r.LastName),
			NickName:          fromPgText(r.NickName),
			ProfilePictureURL: fromPgText(r.ProfilePictureUrl),
			Role:              r.Role,
			DisplayOrder:      r.DisplayOrder.Int32,
		}
	}
	return result, nil
}
