package bot import ( "context" "fmt" "log/slog" "time" bot "github.com/go-telegram/bot" "worktimeBot/internal/db" ) // buildStatusText returns the main menu status text for the current user. func (h *Handler) buildStatusText(chatID int64) string { user, day, err := h.getUserToday(chatID) if err != nil { return "Welcome. Choose an action:" } text := fmt.Sprintf("Today: %s", formatDateForCalendar(day.Date, user.Calendar)) if day.IsDayOff { text += "\nDay Off" } wt, _ := h.DB.GetWorkType(day.CurrentWorkTypeID) if wt != nil { text += fmt.Sprintf("\nWork type: %s", wt.Name) } last, err := h.DB.GetLastEvent(user.ID) if err == nil && last != nil && last.EventType == "in" { loc := loadLocation(user.Timezone) t := time.Unix(last.OccurredAt, 0).In(loc).Format("15:04") text += fmt.Sprintf("\nStatus: working since %s", t) } else { text += "\nStatus: not working" } events, err := h.DB.EventsForDayByDayID(day.ID) if err == nil && len(events) > 0 { loc := loadLocation(user.Timezone) now := time.Now().In(loc) y, m, d := now.Date() dayStart := time.Date(y, m, d, 0, 0, 0, 0, loc).Unix() dayEnd := now.Unix() totals := ComputeDailyTotals(events, day.MinBreakThreshold, dayStart, dayEnd) text += fmt.Sprintf("\nToday: %s worked", formatDuration(totals.TotalSeconds)) } text += "\n\nChoose an action:" return text } // backToMenu returns to the main menu from any sub-menu. func (h *Handler) backToMenu(ctx context.Context, chatID int64, msgID int, callbackID string) { defer h.answerCb(ctx, callbackID) kb := mainKeyboard() h.editText(ctx, chatID, msgID, h.buildStatusText(chatID), &kb) } // buildDailyReport builds a formatted daily report string for a given user/day. func (h *Handler) buildDailyReport(user *db.User, day *db.Day, events []db.Event) string { loc, err := time.LoadLocation(user.Timezone) if err != nil { loc = time.UTC } if len(events) == 0 { if day.IsDayOff { return fmt.Sprintf("%s - Day Off", formatDateForCalendar(day.Date, user.Calendar)) } return fmt.Sprintf("%s - No events recorded.", formatDateForCalendar(day.Date, user.Calendar)) } y, m, d := parseGregorianDateKey(day.Date) dayStart := time.Date(y, time.Month(m), d, 0, 0, 0, 0, loc).Unix() now := time.Now().In(loc) todayStr := now.Format("2006-01-02") dayEnd := time.Date(y, time.Month(m), d, 23, 59, 59, 0, loc).Unix() if day.Date == todayStr { dayEnd = now.Unix() } totals := ComputeDailyTotals(events, day.MinBreakThreshold, dayStart, dayEnd) lines := fmt.Sprintf("Report for %s", formatDateForCalendar(day.Date, user.Calendar)) if day.IsDayOff { lines += "\nDay Off: Yes" } lines += "\n\n" for _, e := range events { t := time.Unix(e.OccurredAt, 0).In(loc).Format("15:04") label := "IN" if e.EventType == "out" { label = "OUT" } suffix := "" if e.WorkTypeID != nil { if wtObj, err := h.DB.GetWorkType(*e.WorkTypeID); err == nil { suffix = " [" + wtObj.Name + "]" } } if e.Note != "" { suffix += " (" + e.Note + ")" } lines += fmt.Sprintf("%s %s%s\n", label, t, suffix) } lines += fmt.Sprintf("\nSummary:\n Work: %s\n Break: %s\n", formatDuration(totals.TotalSeconds), formatDuration(totals.BreakSeconds)) return lines } // SendDailyReport sends the automated daily report to the user. func (h *Handler) SendDailyReport(ctx context.Context, userID int64, chatID int64) { user, err := h.DB.GetUserByChatID(chatID) if err != nil { slog.Error("daily report: user not found", "user_id", userID) return } loc, err := time.LoadLocation(user.Timezone) if err != nil { loc = time.UTC } now := time.Now().In(loc) today := now.Format("2006-01-02") day, err := h.DB.GetOrCreateDay(user.ID, today) if err != nil { slog.Error("daily report: get day", "error", err) return } events, err := h.DB.EventsForDayByDayID(day.ID) if err != nil { slog.Error("daily report: get events", "error", err) return } text := h.buildDailyReport(user, day, events) _, err = h.Bot.SendMessage(ctx, &bot.SendMessageParams{ChatID: chatID, Text: text}) if err != nil { slog.Error("daily report: send message failed", "chat_id", chatID, "error", err) return } if err := h.DB.MarkReportSent(user.ID, today); err != nil { slog.Error("daily report: mark sent failed", "chat_id", chatID, "error", err) } }