package service import ( "time" "github.com/daniil/homelab-api/internal/model" "github.com/daniil/homelab-api/internal/repository" ) type HabitService struct { habitRepo *repository.HabitRepository } func NewHabitService(habitRepo *repository.HabitRepository) *HabitService { return &HabitService{habitRepo: habitRepo} } func (s *HabitService) Create(userID int64, req *model.CreateHabitRequest) (*model.Habit, error) { habit := &model.Habit{ UserID: userID, Name: req.Name, Description: req.Description, Color: defaultString(req.Color, "#6366f1"), Icon: defaultString(req.Icon, "check"), Frequency: defaultString(req.Frequency, "daily"), TargetDays: req.TargetDays, TargetCount: defaultInt(req.TargetCount, 1), } if err := s.habitRepo.Create(habit); err != nil { return nil, err } return habit, nil } func (s *HabitService) Get(id, userID int64) (*model.Habit, error) { return s.habitRepo.GetByID(id, userID) } func (s *HabitService) List(userID int64, includeArchived bool) ([]model.Habit, error) { habits, err := s.habitRepo.ListByUser(userID, includeArchived) if err != nil { return nil, err } if habits == nil { habits = []model.Habit{} } return habits, nil } func (s *HabitService) Update(id, userID int64, req *model.UpdateHabitRequest) (*model.Habit, error) { habit, err := s.habitRepo.GetByID(id, userID) if err != nil { return nil, err } if req.Name != nil { habit.Name = *req.Name } if req.Description != nil { habit.Description = *req.Description } if req.Color != nil { habit.Color = *req.Color } if req.Icon != nil { habit.Icon = *req.Icon } if req.Frequency != nil { habit.Frequency = *req.Frequency } if req.TargetDays != nil { habit.TargetDays = req.TargetDays } if req.TargetCount != nil { habit.TargetCount = *req.TargetCount } if req.IsArchived != nil { habit.IsArchived = *req.IsArchived } if err := s.habitRepo.Update(habit); err != nil { return nil, err } return habit, nil } func (s *HabitService) Delete(id, userID int64) error { return s.habitRepo.Delete(id, userID) } func (s *HabitService) Log(habitID, userID int64, req *model.LogHabitRequest) (*model.HabitLog, error) { // Verify habit exists and belongs to user if _, err := s.habitRepo.GetByID(habitID, userID); err != nil { return nil, err } date := time.Now().Truncate(24 * time.Hour) if req.Date != "" { parsed, err := time.Parse("2006-01-02", req.Date) if err != nil { return nil, err } date = parsed } log := &model.HabitLog{ HabitID: habitID, UserID: userID, Date: date, Count: defaultInt(req.Count, 1), Note: req.Note, } if err := s.habitRepo.CreateLog(log); err != nil { return nil, err } return log, nil } func (s *HabitService) GetLogs(habitID, userID int64, days int) ([]model.HabitLog, error) { // Verify habit exists and belongs to user if _, err := s.habitRepo.GetByID(habitID, userID); err != nil { return nil, err } to := time.Now() from := to.AddDate(0, 0, -days) logs, err := s.habitRepo.GetLogs(habitID, userID, from, to) if err != nil { return nil, err } if logs == nil { logs = []model.HabitLog{} } return logs, nil } func (s *HabitService) DeleteLog(logID, userID int64) error { return s.habitRepo.DeleteLog(logID, userID) } func (s *HabitService) GetHabitStats(habitID, userID int64) (*model.HabitStats, error) { // Verify habit exists and belongs to user if _, err := s.habitRepo.GetByID(habitID, userID); err != nil { return nil, err } return s.habitRepo.GetStats(habitID, userID) } func (s *HabitService) GetOverallStats(userID int64) (*model.OverallStats, error) { habits, err := s.habitRepo.ListByUser(userID, false) if err != nil { return nil, err } allHabits, err := s.habitRepo.ListByUser(userID, true) if err != nil { return nil, err } todayLogs, err := s.habitRepo.GetUserLogsForDate(userID, time.Now().Truncate(24*time.Hour)) if err != nil { return nil, err } return &model.OverallStats{ TotalHabits: len(allHabits), ActiveHabits: len(habits), TodayCompleted: len(todayLogs), }, nil } func defaultString(val, def string) string { if val == "" { return def } return val } func defaultInt(val, def int) int { if val == 0 { return def } return val }