package repository import ( "context" "time" "github.com/bnema/dumber/internal/domain/entity" ) // HistoryScope constrains a history query to an optional age window. Cutoff is // the inclusive lower bound for an entry's last_visited timestamp. The zero // time disables age filtering, so all stored history is eligible. type HistoryScope struct { Cutoff time.Time } // HistoryRepository defines operations for browsing history persistence. type HistoryRepository interface { // Save creates or updates a history entry (upsert). Save(ctx context.Context, entry *entity.HistoryEntry) error // FindByURL retrieves a history entry by its URL. FindByURL(ctx context.Context, url string) (*entity.HistoryEntry, error) // Search performs a fuzzy search on history entries. Results older than // scope.Cutoff are excluded in SQL before the result limit is applied. A // non-positive limit returns no matches. Search(ctx context.Context, query string, limit int, scope HistoryScope) ([]entity.HistoryMatch, error) // GetRecent retrieves recent history entries with pagination. A non-positive // limit means all entries. Results older than scope.Cutoff are excluded in // SQL before the limit is applied. GetRecent(ctx context.Context, limit, offset int, scope HistoryScope) ([]*entity.HistoryEntry, error) // GetRecentByDomain retrieves recent history entries for a domain with pagination. A zero limit means all matching entries. GetRecentByDomain(ctx context.Context, domain string, limit, offset int) ([]*entity.HistoryEntry, error) // GetRecentWindow retrieves entries older than the stable (last_visited, id) cursor, sorted by recency. GetRecentWindow(ctx context.Context, before time.Time, beforeID int64, limit int) ([]*entity.HistoryEntry, error) // GetRecentWindowByDomain retrieves domain entries older than the stable (last_visited, id) cursor, sorted by recency. GetRecentWindowByDomain(ctx context.Context, domain string, before time.Time, beforeID int64, limit int) ([]*entity.HistoryEntry, error) // GetRecentSince retrieves history entries visited within the last N days. // days must be > 0. GetRecentSince(ctx context.Context, days int) ([]*entity.HistoryEntry, error) // GetMostVisited retrieves history entries sorted by visit count within the last N days. // days must be > 0. GetMostVisited(ctx context.Context, days int) ([]*entity.HistoryEntry, error) // GetMostVisitedWithin retrieves history entries ordered by visit count, // optionally restricted to scope.Cutoff and capped by limit in SQL. A // non-positive limit returns an empty slice. GetMostVisitedWithin(ctx context.Context, limit int, scope HistoryScope) ([]*entity.HistoryEntry, error) // GetAllRecentHistory retrieves all history entries sorted by recency. GetAllRecentHistory(ctx context.Context) ([]*entity.HistoryEntry, error) // GetAllMostVisited retrieves all history entries sorted by visit count. GetAllMostVisited(ctx context.Context) ([]*entity.HistoryEntry, error) // IncrementVisitCount increments the visit count for a URL. IncrementVisitCount(ctx context.Context, url string) error // Delete removes a single history entry by ID. Delete(ctx context.Context, id int64) error // DeleteOlderThan removes entries older than the given time. DeleteOlderThan(ctx context.Context, before time.Time) error // DeleteSince removes entries visited at or after the given time. DeleteSince(ctx context.Context, since time.Time) error // DeleteAll removes all history entries. DeleteAll(ctx context.Context) error // DeleteByDomain removes all history entries for a domain. DeleteByDomain(ctx context.Context, domain string) error // GetStats retrieves overall history statistics. GetStats(ctx context.Context) (*entity.HistoryStats, error) // GetDomainStats retrieves per-domain statistics. GetDomainStats(ctx context.Context, limit int) ([]*entity.DomainStat, error) // GetHourlyDistribution retrieves hourly visit distribution. GetHourlyDistribution(ctx context.Context) ([]*entity.HourlyDistribution, error) // GetDailyVisitCount retrieves daily visit counts for the given period. GetDailyVisitCount(ctx context.Context, daysAgo string) ([]*entity.DailyVisitCount, error) }