package repository import ( "context" "errors" dbgen "Yimaru-Backend/gen/db" "Yimaru-Backend/internal/domain" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" ) func int64PtrToPg8(p *int64) pgtype.Int8 { if p == nil { return pgtype.Int8{Valid: false} } return pgtype.Int8{Int64: *p, Valid: true} } func fromPgInt8ID(c pgtype.Int8) *int64 { if !c.Valid { return nil } v := c.Int64 return &v } func lmsPracticeToDomain(p dbgen.LmsPractice) domain.Practice { out := domain.Practice{ ID: p.ID, Title: p.Title, QuestionSetID: p.QuestionSetID, } if p.CourseID.Valid { out.ParentKind = domain.ParentKindCourse out.ParentID = p.CourseID.Int64 } else if p.ModuleID.Valid { out.ParentKind = domain.ParentKindModule out.ParentID = p.ModuleID.Int64 } else if p.LessonID.Valid { out.ParentKind = domain.ParentKindLesson out.ParentID = p.LessonID.Int64 } out.StoryDescription = fromPgText(p.StoryDescription) out.StoryImage = fromPgText(p.StoryImage) out.QuickTips = fromPgText(p.QuickTips) out.PersonaID = fromPgInt8ID(p.PersonaID) out.CreatedAt = p.CreatedAt.Time if p.UpdatedAt.Valid { t := p.UpdatedAt.Time out.UpdatedAt = &t } return out } func lmsFromListRow( id, qid int64, title string, cid, mid, lid pgtype.Int8, sd, si, qt pgtype.Text, pid pgtype.Int8, ca, ua pgtype.Timestamptz, ) domain.Practice { return lmsPracticeToDomain(dbgen.LmsPractice{ ID: id, CourseID: cid, ModuleID: mid, LessonID: lid, Title: title, StoryDescription: sd, StoryImage: si, PersonaID: pid, QuestionSetID: qid, QuickTips: qt, CreatedAt: ca, UpdatedAt: ua, }) } // CreateLmsPractice sets exactly one of courseID, moduleID, lessonID (non-nil). func (s *Store) CreateLmsPractice( ctx context.Context, in domain.CreatePracticeInput, courseID, moduleID, lessonID *int64, ) (domain.Practice, error) { p, err := s.queries.CreateLmsPractice(ctx, dbgen.CreateLmsPracticeParams{ CourseID: int64PtrToPg8(courseID), ModuleID: int64PtrToPg8(moduleID), LessonID: int64PtrToPg8(lessonID), Title: in.Title, StoryDescription: toPgText(in.StoryDescription), StoryImage: toPgText(in.StoryImage), PersonaID: int64PtrToPg8(in.PersonaID), QuestionSetID: in.QuestionSetID, QuickTips: toPgText(in.QuickTips), }) if err != nil { return domain.Practice{}, err } return lmsPracticeToDomain(p), nil } func (s *Store) GetLmsPracticeByID(ctx context.Context, id int64) (domain.Practice, error) { p, err := s.queries.GetLmsPracticeByID(ctx, id) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return domain.Practice{}, pgx.ErrNoRows } return domain.Practice{}, err } return lmsPracticeToDomain(p), nil } func (s *Store) ListLmsPracticesByCourseID(ctx context.Context, courseID int64, limit, offset int32) ([]domain.Practice, int64, error) { rows, err := s.queries.ListLmsPracticesByCourseID(ctx, dbgen.ListLmsPracticesByCourseIDParams{ CourseID: pgtype.Int8{Int64: courseID, Valid: true}, Limit: limit, Offset: offset, }) if err != nil { return nil, 0, err } if len(rows) == 0 { return []domain.Practice{}, 0, nil } var total int64 out := make([]domain.Practice, 0, len(rows)) for i, r := range rows { if i == 0 { total = r.TotalCount } out = append(out, lmsFromListRow( r.ID, r.QuestionSetID, r.Title, r.CourseID, r.ModuleID, r.LessonID, r.StoryDescription, r.StoryImage, r.QuickTips, r.PersonaID, r.CreatedAt, r.UpdatedAt, )) } return out, total, nil } func (s *Store) ListLmsPracticesByModuleID(ctx context.Context, moduleID int64, limit, offset int32) ([]domain.Practice, int64, error) { rows, err := s.queries.ListLmsPracticesByModuleID(ctx, dbgen.ListLmsPracticesByModuleIDParams{ ModuleID: pgtype.Int8{Int64: moduleID, Valid: true}, Limit: limit, Offset: offset, }) if err != nil { return nil, 0, err } if len(rows) == 0 { return []domain.Practice{}, 0, nil } var total int64 out := make([]domain.Practice, 0, len(rows)) for i, r := range rows { if i == 0 { total = r.TotalCount } out = append(out, lmsFromListRow( r.ID, r.QuestionSetID, r.Title, r.CourseID, r.ModuleID, r.LessonID, r.StoryDescription, r.StoryImage, r.QuickTips, r.PersonaID, r.CreatedAt, r.UpdatedAt, )) } return out, total, nil } func (s *Store) ListLmsPracticesByLessonID(ctx context.Context, lessonID int64, limit, offset int32) ([]domain.Practice, int64, error) { rows, err := s.queries.ListLmsPracticesByLessonID(ctx, dbgen.ListLmsPracticesByLessonIDParams{ LessonID: pgtype.Int8{Int64: lessonID, Valid: true}, Limit: limit, Offset: offset, }) if err != nil { return nil, 0, err } if len(rows) == 0 { return []domain.Practice{}, 0, nil } var total int64 out := make([]domain.Practice, 0, len(rows)) for i, r := range rows { if i == 0 { total = r.TotalCount } out = append(out, lmsFromListRow( r.ID, r.QuestionSetID, r.Title, r.CourseID, r.ModuleID, r.LessonID, r.StoryDescription, r.StoryImage, r.QuickTips, r.PersonaID, r.CreatedAt, r.UpdatedAt, )) } return out, total, nil } func optionalInt8UpdateID(val *int64) pgtype.Int8 { if val == nil { return pgtype.Int8{Valid: false} } return pgtype.Int8{Int64: *val, Valid: true} } func (s *Store) UpdateLmsPractice(ctx context.Context, id int64, input domain.UpdatePracticeInput) (domain.Practice, error) { var titleText pgtype.Text if input.Title != nil { titleText = pgtype.Text{String: *input.Title, Valid: true} } else { titleText = pgtype.Text{Valid: false} } qs := optionalInt8UpdateID(input.QuestionSetID) p, err := s.queries.UpdateLmsPractice(ctx, dbgen.UpdateLmsPracticeParams{ ID: id, Title: titleText, StoryDescription: optionalTextUpdate(input.StoryDescription), StoryImage: optionalTextUpdate(input.StoryImage), PersonaID: optionalInt8UpdateID(input.PersonaID), QuestionSetID: qs, QuickTips: optionalTextUpdate(input.QuickTips), }) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return domain.Practice{}, pgx.ErrNoRows } return domain.Practice{}, err } return lmsPracticeToDomain(p), nil } func (s *Store) DeleteLmsPractice(ctx context.Context, id int64) error { return s.queries.DeleteLmsPractice(ctx, id) }