1package services
2
3import (
4 "context"
5 "database/sql"
6 "fmt"
7
8 "github.com/bnema/dumber/internal/config"
9 "github.com/bnema/dumber/internal/db"
10 "github.com/bnema/dumber/internal/parser"
11)
12
13// ParserService wraps the parser functionality for the application.
14type ParserService struct {
15 parser *parser.Parser
16 dbQueries *db.Queries
17}
18
19// NewParserService creates a new ParserService instance.
20func NewParserService(cfg *config.Config, queries *db.Queries) *ParserService {
21 // Create history provider from database
22 historyProvider := &DatabaseHistoryProvider{queries: queries}
23
24 // Create parser with configuration
25 p := parser.NewParser(cfg, historyProvider)
26
27 return &ParserService{
28 parser: p,
29 dbQueries: queries,
30 }
31}
32
33// ParseInput parses user input and returns navigation result.
34func (s *ParserService) ParseInput(ctx context.Context, input string) (*parser.ParseResult, error) {
35 _ = ctx
36 if input == "" {
37 return nil, fmt.Errorf("input cannot be empty")
38 }
39
40 return s.parser.ParseInput(input)
41}
42
43// GetCompletions provides URL/search completions based on input.
44func (s *ParserService) GetCompletions(ctx context.Context, input string, limit int) ([]string, error) {
45 _ = ctx
46 if limit <= 0 {
47 limit = 10 // Default limit
48 }
49
50 return s.parser.SuggestCompletions(input, limit)
51}
52
53// FuzzySearchHistory performs fuzzy search on history entries.
54func (s *ParserService) FuzzySearchHistory(
55 ctx context.Context, query string, threshold float64,
56) ([]parser.FuzzyMatch, error) {
57 _ = ctx
58 if threshold <= 0 {
59 threshold = 0.3 // Default threshold
60 }
61
62 return s.parser.FuzzySearchHistory(query, threshold)
63}
64
65// GetSupportedShortcuts returns configured search shortcuts.
66func (s *ParserService) GetSupportedShortcuts(ctx context.Context) (map[string]config.SearchShortcut, error) {
67 _ = ctx
68 return s.parser.GetSupportedShortcuts(), nil
69}
70
71// ProcessShortcut processes a shortcut and returns the resulting URL.
72func (s *ParserService) ProcessShortcut(ctx context.Context, shortcut, query string) (string, error) {
73 _ = ctx
74 shortcuts := s.parser.GetSupportedShortcuts()
75 return s.parser.ProcessShortcut(shortcut, query, shortcuts)
76}
77
78// CalculateSimilarity calculates similarity between two strings.
79func (s *ParserService) CalculateSimilarity(ctx context.Context, s1, s2 string) (float64, error) {
80 _ = ctx
81 return s.parser.CalculateSimilarity(s1, s2), nil
82}
83
84// ValidateURL checks if the input represents a valid URL.
85func (s *ParserService) ValidateURL(ctx context.Context, input string) (bool, error) {
86 _ = ctx
87 return s.parser.IsValidURL(input), nil
88}
89
90// PreviewParse provides a preview of what ParseInput would return.
91func (s *ParserService) PreviewParse(ctx context.Context, input string) (*parser.ParseResult, error) {
92 _ = ctx
93 if input == "" {
94 return nil, fmt.Errorf("input cannot be empty")
95 }
96
97 return s.parser.PreviewParse(input)
98}
99
100// GetFuzzyConfig returns current fuzzy matching configuration.
101func (s *ParserService) GetFuzzyConfig(ctx context.Context) (*parser.FuzzyConfig, error) {
102 _ = ctx
103 return s.parser.GetFuzzyConfig(), nil
104}
105
106// UpdateFuzzyConfig updates the fuzzy matching configuration.
107func (s *ParserService) UpdateFuzzyConfig(ctx context.Context, config *parser.FuzzyConfig) error {
108 _ = ctx
109 return s.parser.UpdateFuzzyConfig(config)
110}
111
112// DatabaseHistoryProvider implements HistoryProvider using the database.
113type DatabaseHistoryProvider struct {
114 queries *db.Queries
115}
116
117// GetRecentHistory returns recent history entries limited by count.
118func (h *DatabaseHistoryProvider) GetRecentHistory(limit int) ([]*db.History, error) {
119 ctx := context.Background()
120
121 entries, err := h.queries.GetHistory(ctx, int64(limit))
122 if err != nil {
123 return nil, err
124 }
125
126 // Convert to pointer slice
127 result := make([]*db.History, len(entries))
128 for i, entry := range entries {
129 entryCopy := entry
130 result[i] = &entryCopy
131 }
132
133 return result, nil
134}
135
136// GetAllHistory returns all history entries for fuzzy search.
137func (h *DatabaseHistoryProvider) GetAllHistory() ([]*db.History, error) {
138 ctx := context.Background()
139
140 // Use a large limit to get all history
141 const allHistoryLimit = 10000
142 entries, err := h.queries.GetHistory(ctx, allHistoryLimit)
143 if err != nil {
144 return nil, err
145 }
146
147 // Convert to pointer slice
148 result := make([]*db.History, len(entries))
149 for i, entry := range entries {
150 entryCopy := entry
151 result[i] = &entryCopy
152 }
153
154 return result, nil
155}
156
157// SearchHistory performs a basic text search in history.
158func (h *DatabaseHistoryProvider) SearchHistory(query string, limit int) ([]*db.History, error) {
159 ctx := context.Background()
160
161 // Use SQL LIKE pattern for basic search
162 urlPattern := sql.NullString{String: "%" + query + "%", Valid: true}
163 titlePattern := sql.NullString{String: "%" + query + "%", Valid: true}
164
165 entries, err := h.queries.SearchHistory(ctx, urlPattern, titlePattern, int64(limit))
166 if err != nil {
167 return nil, err
168 }
169
170 // Convert to pointer slice
171 result := make([]*db.History, len(entries))
172 for i, entry := range entries {
173 entryCopy := entry
174 result[i] = &entryCopy
175 }
176
177 return result, nil
178}
179
180// GetHistoryByURL retrieves history entry by exact URL match.
181func (h *DatabaseHistoryProvider) GetHistoryByURL(url string) (*db.History, error) {
182 ctx := context.Background()
183
184 // Search for exact URL match using SearchHistory
185 urlPattern := sql.NullString{String: url, Valid: true}
186 emptyPattern := sql.NullString{Valid: false}
187
188 entries, err := h.queries.SearchHistory(ctx, urlPattern, emptyPattern, 1)
189 if err != nil {
190 return nil, err
191 }
192
193 if len(entries) == 0 {
194 return nil, fmt.Errorf("history entry not found for URL: %s", url)
195 }
196
197 return &entries[0], nil
198}