package service import ( "context" "errors" "strings" "time" "watch-party-backend/internal/repo" ) var ErrInvalidTime = errors.New("invalid start_time (expected HH:MM or HH:MM:SS)") type EpisodeService interface { GetCurrent(ctx context.Context) (repo.Episode, error) SetCurrent(ctx context.Context, id int64, start string) (repo.Episode, error) } type episodeService struct { repo repo.EpisodeRepository } func NewEpisodeService(r repo.EpisodeRepository) EpisodeService { return &episodeService{repo: r} } func (s *episodeService) GetCurrent(ctx context.Context) (repo.Episode, error) { c, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() return s.repo.GetCurrent(c) } func (s *episodeService) SetCurrent(ctx context.Context, id int64, start string) (repo.Episode, error) { // normalize and validate time as HH:MM:SS normalized, err := normalizeHHMMSS(start) if err != nil { return repo.Episode{}, ErrInvalidTime } c, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() // do the transaction if err := s.repo.SetCurrent(c, id, normalized); err != nil { return repo.Episode{}, err } // return the new current row return s.repo.GetCurrent(c) } func normalizeHHMMSS(s string) (string, error) { s = strings.TrimSpace(s) if len(s) == 5 { // HH:MM → append seconds s += ":00" } // Strict parse/format to 24h t, err := time.Parse("15:04:05", s) if err != nil { return "", err } return t.Format("15:04:05"), nil }