func (r *ChoreRepository) CompleteChore(c context.Context, chore *chModel.Chore, note *string, userID int, dueDate *time.Time, completedDate *time.Time, nextAssignedTo *int, applyPoints bool) error {
	nextVersion, err := r.nextSyncVersion(c, chore.CircleID)
	if err != nil {
		return err
	}
	err = r.db.WithContext(c).Transaction(func(tx *gorm.DB) error {

		choreUpdates := map[string]interface{}{}
		choreUpdates["next_due_date"] = dueDate
		choreUpdates["status"] = chModel.ChoreStatusNoStatus
		choreUpdates["sync_version"] = nextVersion

		switch {
		case dueDate != nil:
			choreUpdates["assigned_to"] = nextAssignedTo
		case chore.FrequencyType == "trigger":
			// In case of trigger frequency type we need to still set the next assigned but need the task archived.
			choreUpdates["assigned_to"] = nextAssignedTo
			choreUpdates["is_active"] = false
		case chore.FrequencyType == "always":
			// Always chores have no due date but stay active and available immediately after completion.
			choreUpdates["assigned_to"] = nextAssignedTo
		default:
			// one time task
			choreUpdates["is_active"] = false
		}

		// Look for existing chore history with start or pause status
		var existingHistory chModel.ChoreHistory
		err := tx.Where("chore_id = ? AND status = ? ",
			chore.ID, chModel.ChoreHistoryStatusStarted).
			First(&existingHistory).Error

		var ch *chModel.ChoreHistory
		switch {
		case err == nil:
			// Update existing history record
			existingHistory.PerformedAt = completedDate
			existingHistory.Note = note
			existingHistory.Status = chModel.ChoreHistoryStatusCompleted
			ch = &existingHistory
		case errors.Is(err, gorm.ErrRecordNotFound):
			// Create a new chore history record
			ch = &chModel.ChoreHistory{
				ChoreID:     chore.ID,
				PerformedAt: completedDate,
				CompletedBy: userID,
				AssignedTo:  chore.AssignedTo,
				DueDate:     chore.NextDueDate,
				Note:        note,
				Status:      chModel.ChoreHistoryStatusCompleted,
			}
		default:
			return err
		}

		// Update UserCirclee Points :
		if applyPoints && chore.Points != nil && *chore.Points > 0 {
			ch.Points = chore.Points
			if err := tx.Model(&cModel.UserCircle{}).Where("user_id = ? AND circle_id = ?", userID, chore.CircleID).Update("points", gorm.Expr("points + ?", chore.Points)).Error; err != nil {
				return err
			}
		}
		ch.SyncVersion = nextVersion
		// Perform the update operation once, using the prepared updates map.
		if err := tx.Model(&chModel.Chore{}).Where("id = ?", chore.ID).Updates(choreUpdates).Error; err != nil {
			return err
		}

		if err := tx.Save(ch).Error; err != nil {
			return err
		}
		// if there is any time session associated with the chore, mark them as finished:
		var timeSessions []*chModel.TimeSession
		tx.Model(&chModel.TimeSession{}).Where("chore_id = ? AND status < ?", chore.ID, chModel.TimeSessionStatusCompleted).Find(&timeSessions)
		if len(timeSessions) != 0 {
			for _, session := range timeSessions {
				session.Finish(userID)
			}
			if err := tx.Save(&timeSessions).Error; err != nil {
				return err
			}
		}

		return nil
	})
	return err
}

func (r *ChoreRepository) SkipChore(c context.Context, chore *chModel.Chore, userID int, dueDate *time.Time, nextAssignedTo *int, skippedAt *time.Time) error {
	nextVersion, err := r.nextSyncVersion(c, chore.CircleID)
	if err != nil {
		return err
	}
	err = r.db.WithContext(c).Transaction(func(tx *gorm.DB) error {
		choreUpdates := map[string]interface{}{}
		choreUpdates["next_due_date"] = dueDate
		choreUpdates["status"] = chModel.ChoreStatusNoStatus
		choreUpdates["sync_version"] = nextVersion

		if dueDate != nil {
			choreUpdates["assigned_to"] = nextAssignedTo
		} else {
			// one time task
			choreUpdates["is_active"] = false
		}

		// Look for existing chore history with start or pause status
		var existingHistory chModel.ChoreHistory
		err := tx.Where("chore_id = ? AND status = ? ",
			chore.ID, chModel.ChoreHistoryStatusStarted).
			First(&existingHistory).Error

		var ch *chModel.ChoreHistory
		effectiveSkippedAt := time.Now().UTC()
		if skippedAt != nil {
			effectiveSkippedAt = skippedAt.UTC()
		}

		switch {
		case err == nil && existingHistory.PerformedAt != nil:
			// Update existing history record
			existingHistory.PerformedAt = &effectiveSkippedAt
			existingHistory.Note = nil
			existingHistory.Status = chModel.ChoreHistoryStatusSkipped
			ch = &existingHistory
		case errors.Is(err, gorm.ErrRecordNotFound):
			// Create a new chore history record for the skipped chore
			ch = &chModel.ChoreHistory{
				ChoreID:     chore.ID,
				PerformedAt: &effectiveSkippedAt,
				CompletedBy: userID,
				AssignedTo:  chore.AssignedTo,
				DueDate:     chore.NextDueDate,
				Note:        nil,
				Status:      chModel.ChoreHistoryStatusSkipped,
			}
		default:
			return err
		}

		ch.SyncVersion = nextVersion
		// Perform the update operation once, using the prepared updates map.
		if err := tx.Model(&chModel.Chore{}).Where("id = ?", chore.ID).Updates(choreUpdates).Error; err != nil {
			return err
		}

		if err := tx.Save(ch).Error; err != nil {
			return err
		}

		// if there is any time session associated with the chore, mark them as finished:
		var timeSessions []*chModel.TimeSession
		tx.Model(&chModel.TimeSession{}).Where("chore_id = ? AND status < ?", chore.ID, chModel.TimeSessionStatusCompleted).Find(&timeSessions)
		if len(timeSessions) != 0 {
			for _, session := range timeSessions {
				session.Finish(userID)
			}
