Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.14% covered (danger)
0.14%
1 / 712
14.29% covered (danger)
14.29%
1 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
FlyMsgUserDailyUsageService
0.14% covered (danger)
0.14%
1 / 712
14.29% covered (danger)
14.29%
1 / 7
2246.71
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 refresh
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 processUserSummaryUsage2
0.00% covered (danger)
0.00%
0 / 138
0.00% covered (danger)
0.00%
0 / 1
56
 processUserSummaryUsage
0.00% covered (danger)
0.00%
0 / 210
0.00% covered (danger)
0.00%
0 / 1
30
 processUserUsage
0.00% covered (danger)
0.00%
0 / 275
0.00% covered (danger)
0.00%
0 / 1
552
 parseMonth
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 getHubspotUsage
0.00% covered (danger)
0.00%
0 / 72
0.00% covered (danger)
0.00%
0 / 1
90
1<?php
2
3namespace App\Services\UserInfo;
4
5use App\Http\Models\Admin\CompanyGroup;
6use App\Http\Models\Auth\User;
7use App\Http\Models\FlyCutUsage;
8use App\Http\Models\FlyGrammarActions;
9use App\Http\Models\FlyMsgUserDailyUsage;
10use App\Http\Models\HubspotProperties;
11use App\Http\Models\Shortcut;
12use App\Http\Models\UserInfo;
13use App\Http\Services\StatisticsService;
14use App\Traits\UsageTrait;
15use Illuminate\Support\Carbon;
16use MongoDB\BSON\UTCDateTime;
17
18class FlyMsgUserDailyUsageService
19{
20    use UsageTrait;
21
22    public function __construct(
23        private StatisticsService $statisticsService
24    ) {}
25
26    public function refresh(FlyMsgUserDailyUsage $usage): void
27    {
28        $user = User::find($usage->user_id);
29
30        $this->processUserSummaryUsage($user);
31    }
32
33    public function processUserSummaryUsage2(User $user)
34    {
35        $userInfo = UserInfo::where('email', $user->email)->first();
36
37        $startDate = $user->created_at;
38
39        if ($startDate->lessThan(Carbon::parse('2022-01-01 00:00:00'))) {
40            $startDate = Carbon::parse('2022-01-01 00:00:00');
41        }
42
43        $endDate = now()->endOfDay();
44
45        $sentence_rewrite_summarized = [];
46        $paragraph_rewrite_summarized = [];
47        $fly_engage_summarized = [];
48        $fly_post_summarized = [];
49        $fly_cut_summarized = [];
50        $time_saved_summarized = [];
51        $cost_savings_summarized = [];
52        $characters_typed_summarized = [];
53        while ($startDate->lessThanOrEqualTo($endDate)) {
54            $year = $startDate->year;
55            $month = $this->parseMonth($startDate->month);
56
57            $totalTimeSavedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('time_saved');
58            $totalCostSavingsThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('cost_savings');
59            $totalCharactersTypedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('characters_typed');
60
61            $userInfo->{"total_time_saved___{$month}_{$year}"} = $totalTimeSavedThisMonth;
62            $userInfo->{"total_cost_savings___{$month}_{$year}"} = $totalCostSavingsThisMonth;
63            $userInfo->{"of_characters_typed___{$month}_{$year}"} = $totalCharactersTypedThisMonth;
64
65            $formattedDate = $startDate->format('M Y');
66
67            if ($year >= 2023) {
68                $totalFlyPostUsedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('flypost_count');
69                $totalFlyEngageUsedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('flyengage_count');
70                $totalSentenceRewriteUsedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('sentence_rewrite_count');
71                $totalParagraphRewriteUsedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('paragraph_rewrite_count');
72                $totalFlyCutUsedThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('flycut_count');
73                $totalFlyGrammarActionsThisMonth = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->where('year', $year)->where('month', $startDate->month)->sum('fly_grammar_actions');
74
75                $sentence_rewrite_summarized[] = [
76                    'date' => $startDate->timestamp,
77                    'month' => $formattedDate,
78                    'total' => $totalSentenceRewriteUsedThisMonth,
79                ];
80
81                $paragraph_rewrite_summarized[] = [
82                    'date' => $startDate->timestamp,
83                    'month' => $formattedDate,
84                    'total' => $totalParagraphRewriteUsedThisMonth,
85                ];
86
87                $fly_engage_summarized[] = [
88                    'date' => $startDate->timestamp,
89                    'month' => $formattedDate,
90                    'total' => $totalFlyEngageUsedThisMonth,
91                ];
92
93                $fly_post_summarized[] = [
94                    'date' => $startDate->timestamp,
95                    'month' => $formattedDate,
96                    'total' => $totalFlyPostUsedThisMonth,
97                ];
98
99                $fly_cut_summarized[] = [
100                    'date' => $startDate->timestamp,
101                    'month' => $formattedDate,
102                    'total' => $totalFlyCutUsedThisMonth,
103                ];
104
105                $fly_grammar_actions_summarized[] = [
106                    'date' => $startDate->timestamp,
107                    'month' => $formattedDate,
108                    'total' => $totalFlyGrammarActionsThisMonth,
109                ];
110            }
111
112            $time_saved_summarized[] = [
113                'date' => $startDate->timestamp,
114                'month' => $formattedDate,
115                'total' => $totalTimeSavedThisMonth,
116            ];
117
118            $cost_savings_summarized[] = [
119                'date' => $startDate->timestamp,
120                'month' => $formattedDate,
121                'total' => $totalCostSavingsThisMonth,
122            ];
123
124            $characters_typed_summarized[] = [
125                'date' => $startDate->timestamp,
126                'month' => $formattedDate,
127                'total' => $totalCharactersTypedThisMonth,
128            ];
129
130            $startDate->addMonth();
131            // if same month as endDate
132            if ($startDate->month == $endDate->month && $startDate->year == $endDate->year && $startDate->greaterThan($endDate)) {
133                $startDate = $endDate->copy();
134            }
135        }
136
137        $time_saved_summarized = collect($time_saved_summarized)->sortByDesc('date')->values();
138        $time_saved_summarized = $time_saved_summarized->map(function ($item) {
139            return $item['total'].' - '.$item['month'];
140        });
141
142        $cost_savings_summarized = collect($cost_savings_summarized)->sortByDesc('date')->values();
143        $cost_savings_summarized = $cost_savings_summarized->map(function ($item) {
144            return $item['total'].' - '.$item['month'];
145        });
146
147        $characters_typed_summarized = collect($characters_typed_summarized)->sortByDesc('date')->values();
148        $characters_typed_summarized = $characters_typed_summarized->map(function ($item) {
149            return $item['total'].' - '.$item['month'];
150        });
151
152        $fly_cut_summarized = collect($fly_cut_summarized)->sortByDesc('date')->values();
153        $fly_cut_summarized = $fly_cut_summarized->map(function ($item) {
154            return $item['total'].' - '.$item['month'];
155        });
156
157        $fly_engage_summarized = collect($fly_engage_summarized)->sortByDesc('date')->values();
158        $fly_engage_summarized = $fly_engage_summarized->map(function ($item) {
159            return $item['total'].' - '.$item['month'];
160        });
161
162        $sentence_rewrite_summarized = collect($sentence_rewrite_summarized)->sortByDesc('date')->values();
163        $sentence_rewrite_summarized = $sentence_rewrite_summarized->map(function ($item) {
164            return $item['total'].' - '.$item['month'];
165        });
166        $paragraph_rewrite_summarized = collect($paragraph_rewrite_summarized)->sortByDesc('date')->values();
167        $paragraph_rewrite_summarized = $paragraph_rewrite_summarized->map(function ($item) {
168            return $item['total'].' - '.$item['month'];
169        });
170
171        $fly_post_summarized = collect($fly_post_summarized)->sortByDesc('date')->values();
172        $fly_post_summarized = $fly_post_summarized->map(function ($item) {
173            return $item['total'].' - '.$item['month'];
174        });
175
176        $fly_grammar_actions_summarized = collect($fly_grammar_actions_summarized)->sortByDesc('date')->values();
177        $fly_grammar_actions_summarized = $fly_grammar_actions_summarized->map(function ($item) {
178            return $item['total'].' - '.$item['month'];
179        });
180
181        $userInfo->total_time_saved_summarized_monthly_by_flymsg_by_user = $time_saved_summarized->implode('.   ');
182        $userInfo->total_cost_savings_summarized_monthly_by_flymsg_by_user = $cost_savings_summarized->implode('.   ');
183        $userInfo->total___of_characters_typed_monthly_by_flymsg_by_user = $characters_typed_summarized->implode('.   ');
184        $userInfo->total___of_times_flycut_is_used_summarized_monthly_by_user__count_ = $fly_cut_summarized->implode('.   ');
185        $userInfo->total___of_times_sentence_rewrite_is_used_summarized_monthly_by_user = $sentence_rewrite_summarized->implode('.   ');
186        $userInfo->total___of_times_paragraph_rewrite_is_used_summarized_monthly_by_user = $paragraph_rewrite_summarized->implode('.   ');
187        $userInfo->total___of_times_flyengage_is_used_summarized_monthly_by_user = $fly_engage_summarized->implode('.   ');
188        $userInfo->total___of_times_flyposts_is_used_summarized_monthly_by_user__count_ = $fly_post_summarized->implode('.   ');
189        $userInfo->total___of_times_flygrammar_is_used_summarized_monthly_by_user__count_ = $fly_grammar_actions_summarized->implode('.   ');
190
191        $userInfo->total___of_times_sentence_rewrite_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('sentence_rewrite_count');
192        $userInfo->total___of_times_paragraph_rewrite_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('paragraph_rewrite_count');
193        $userInfo->total___of_times_flyengage_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('flyengage_count');
194        $userInfo->total___of_times_flyposts_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('flypost_count');
195        $userInfo->total___of_times_flycut_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('flycut_count');
196        $userInfo->total___of_times_flygrammar_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('fly_grammar_actions');
197        $userInfo->total___of_times_flygrammar_accepted_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('fly_grammar_accepted');
198        $userInfo->total___of_times_flygrammar_autocorrect_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('fly_grammar_autocorrect');
199        $userInfo->total___of_times_flygrammar_autocomplete_used__count_ = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('fly_grammar_autocomplete');
200
201        $userInfo->total_time_saved_by_flymsg_by_user = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('time_saved');
202        $userInfo->total_cost_savings_by_flymsg_by_user = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('cost_savings');
203        $userInfo->total___of_characters_typed_by_flymsg_by_user = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('characters_typed');
204        $userInfo->number_of_flycuts_created_count = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('flycuts_created');
205        $userInfo->number_of_flyplates_in_flycuts_count = FlyMsgUserDailyUsage::where('user_id', $userInfo->user_id)->sum('flyplates_added');
206
207        $userInfo->save();
208    }
209
210    public function processUserSummaryUsage(User $user)
211    {
212        $userInfo = UserInfo::where('email', $user->email)->first();
213        $startDate = $user->created_at->copy();
214
215        if ($startDate->lessThan(Carbon::parse('2022-01-01 00:00:00'))) {
216            $startDate = Carbon::parse('2022-01-01 00:00:00');
217        }
218
219        $endDate = now()->endOfDay();
220        $user_id = $userInfo->user_id;
221
222        // 1. Consulta agregada mensal com todos os campos relevantes
223        $monthly = FlyMsgUserDailyUsage::raw(function ($collection) use ($user_id, $startDate, $endDate) {
224            return $collection->aggregate([
225                [
226                    '$match' => [
227                        'user_id' => $user_id,
228                        'created_at' => [
229                            '$gte' => new UTCDateTime($startDate->startOfMonth()->timestamp * 1000),
230                            '$lte' => new UTCDateTime($endDate->endOfMonth()->timestamp * 1000),
231                        ],
232                    ],
233                ],
234                [
235                    '$group' => [
236                        '_id' => [
237                            'year' => '$year',
238                            'month' => '$month',
239                        ],
240                        'total_time_saved' => ['$sum' => '$time_saved'],
241                        'total_cost_savings' => ['$sum' => '$cost_savings'],
242                        'total_characters_typed' => ['$sum' => '$characters_typed'],
243                        'flyengage_count' => ['$sum' => '$flyengage_count'],
244                        'sentence_rewrite_count' => ['$sum' => '$sentence_rewrite_count'],
245                        'paragraph_rewrite_count' => ['$sum' => '$paragraph_rewrite_count'],
246                        'flypost_count' => ['$sum' => '$flypost_count'],
247                        'flycut_count' => ['$sum' => '$flycut_count'],
248                        'fly_grammar_actions' => ['$sum' => '$fly_grammar_actions'],
249                        'fly_grammar_accepted' => ['$sum' => '$fly_grammar_accepted'],
250                        'fly_grammar_autocomplete' => ['$sum' => '$fly_grammar_autocomplete'],
251                    ],
252                ],
253                [
254                    '$sort' => ['_id.year' => 1, '_id.month' => 1],
255                ],
256            ]);
257        });
258
259        // 2. Consulta agregada total (não agrupado por mês)
260        $totals = FlyMsgUserDailyUsage::raw(function ($collection) use ($user_id) {
261            return $collection->aggregate([
262                ['$match' => ['user_id' => $user_id]],
263                ['$group' => [
264                    '_id' => null,
265                    'flyengage_count' => ['$sum' => '$flyengage_count'],
266                    'sentence_rewrite_count' => ['$sum' => '$sentence_rewrite_count'],
267                    'paragraph_rewrite_count' => ['$sum' => '$paragraph_rewrite_count'],
268                    'flypost_count' => ['$sum' => '$flypost_count'],
269                    'flycut_count' => ['$sum' => '$flycut_count'],
270                    'total_time_saved' => ['$sum' => '$time_saved'],
271                    'total_cost_savings' => ['$sum' => '$cost_savings'],
272                    'total_characters_typed' => ['$sum' => '$characters_typed'],
273                    'number_of_flycuts_created_count' => ['$sum' => '$flycuts_created'],
274                    'number_of_flyplates_in_flycuts_count' => ['$sum' => '$flyplates_added'],
275                    'fly_grammar_actions' => ['$sum' => '$fly_grammar_actions'],
276                    'fly_grammar_accepted' => ['$sum' => '$fly_grammar_accepted'],
277                    'fly_grammar_autocorrect' => ['$sum' => '$fly_grammar_autocorrect'],
278                ]],
279            ]);
280        });
281        $totals = $totals[0] ?? [];
282
283        // 3. Processamento em memória
284        $sentence_rewrite_summarized = [];
285        $paragraph_rewrite_summarized = [];
286        $fly_engage_summarized = [];
287        $fly_post_summarized = [];
288        $fly_cut_summarized = [];
289        $time_saved_summarized = [];
290        $cost_savings_summarized = [];
291        $characters_typed_summarized = [];
292        $fly_grammar_actions_summarized = [];
293        $fly_grammar_accepted_summarized = [];
294        $fly_grammar_autocorrect_summarized = [];
295        $fly_grammar_autocomplete_summarized = [];
296
297        foreach ($monthly as $item) {
298            $year = $item['_id']['year'];
299            $monthNum = $item['_id']['month'];
300            $month = Carbon::createFromDate($year, $monthNum, 1);
301            $monthKey = strtolower($month->format('F'))."_{$year}";
302            $formattedDate = $month->format('M Y');
303            $timestamp = $month->timestamp;
304
305            // Salva nos campos dinâmicos
306            $userInfo->{"total_time_saved___{$monthKey}"} = $item['total_time_saved'];
307            $userInfo->{"total_cost_savings___{$monthKey}"} = $item['total_cost_savings'];
308            $userInfo->{"of_characters_typed___{$monthKey}"} = $item['total_characters_typed'];
309
310            $time_saved_summarized[] = [
311                'date' => $timestamp,
312                'month' => $formattedDate,
313                'total' => $item['total_time_saved'],
314            ];
315            $cost_savings_summarized[] = [
316                'date' => $timestamp,
317                'month' => $formattedDate,
318                'total' => $item['total_cost_savings'],
319            ];
320            $characters_typed_summarized[] = [
321                'date' => $timestamp,
322                'month' => $formattedDate,
323                'total' => $item['total_characters_typed'],
324            ];
325
326            if ($year >= 2023) {
327                $fly_cut_summarized[] = [
328                    'date' => $timestamp,
329                    'month' => $formattedDate,
330                    'total' => $item['flycut_count'],
331                ];
332                $fly_engage_summarized[] = [
333                    'date' => $timestamp,
334                    'month' => $formattedDate,
335                    'total' => $item['flyengage_count'],
336                ];
337                $fly_post_summarized[] = [
338                    'date' => $timestamp,
339                    'month' => $formattedDate,
340                    'total' => $item['flypost_count'],
341                ];
342            }
343            if ($year >= 2025) {
344                $sentence_rewrite_summarized[] = [
345                    'date' => $timestamp,
346                    'month' => $formattedDate,
347                    'total' => $item['sentence_rewrite_count'],
348                ];
349                $paragraph_rewrite_summarized[] = [
350                    'date' => $timestamp,
351                    'month' => $formattedDate,
352                    'total' => $item['paragraph_rewrite_count'],
353                ];
354                $fly_grammar_actions_summarized[] = [
355                    'date' => $timestamp,
356                    'month' => $formattedDate,
357                    'total' => $item['fly_grammar_actions'],
358                ];
359                $fly_grammar_accepted_summarized[] = [
360                    'date' => $timestamp,
361                    'month' => $formattedDate,
362                    'total' => $item['fly_grammar_accepted'],
363                ];
364                $fly_grammar_autocorrect_summarized[] = [
365                    'date' => $timestamp,
366                    'month' => $formattedDate,
367                    'total' => $item['fly_grammar_autocorrect'],
368                ];
369                $fly_grammar_autocomplete_summarized[] = [
370                    'date' => $timestamp,
371                    'month' => $formattedDate,
372                    'total' => $item['fly_grammar_autocomplete'],
373                ];
374            }
375        }
376
377        // Ordene e formate os arrays
378        $time_saved_summarized = collect($time_saved_summarized)->sortByDesc('date')->values()->map(function ($item) {
379            return $item['total'].' - '.$item['month'];
380        });
381
382        $cost_savings_summarized = collect($cost_savings_summarized)->sortByDesc('date')->values()->map(function ($item) {
383            return $item['total'].' - '.$item['month'];
384        });
385
386        $characters_typed_summarized = collect($characters_typed_summarized)->sortByDesc('date')->values()->map(function ($item) {
387            return $item['total'].' - '.$item['month'];
388        });
389
390        $fly_cut_summarized = collect($fly_cut_summarized)->sortByDesc('date')->values()->map(function ($item) {
391            return $item['total'].' - '.$item['month'];
392        });
393
394        $fly_engage_summarized = collect($fly_engage_summarized)->sortByDesc('date')->values()->map(function ($item) {
395            return $item['total'].' - '.$item['month'];
396        });
397
398        $sentence_rewrite_summarized = collect($sentence_rewrite_summarized)->sortByDesc('date')->values()->map(function ($item) {
399            return $item['total'].' - '.$item['month'];
400        });
401
402        $paragraph_rewrite_summarized = collect($paragraph_rewrite_summarized)->sortByDesc('date')->values()->map(function ($item) {
403            return $item['total'].' - '.$item['month'];
404        });
405
406        $fly_post_summarized = collect($fly_post_summarized)->sortByDesc('date')->values()->map(function ($item) {
407            return $item['total'].' - '.$item['month'];
408        });
409
410        $fly_grammar_actions_summarized = collect($fly_grammar_actions_summarized)->sortByDesc('date')->values()->map(function ($item) {
411            return $item['total'].' - '.$item['month'];
412        });
413        $fly_grammar_accepted_summarized = collect($fly_grammar_accepted_summarized)->sortByDesc('date')->values()->map(function ($item) {
414            return $item['total'].' - '.$item['month'];
415        });
416        $fly_grammar_autocorrect_summarized = collect($fly_grammar_autocorrect_summarized)->sortByDesc('date')->values()->map(function ($item) {
417            return $item['total'].' - '.$item['month'];
418        });
419        $fly_grammar_autocomplete_summarized = collect($fly_grammar_autocomplete_summarized)->sortByDesc('date')->values()->map(function ($item) {
420            return $item['total'].' - '.$item['month'];
421        });
422
423        // Monte os campos finais
424        $userInfo->total_time_saved_summarized_monthly_by_flymsg_by_user = $time_saved_summarized->implode('.   ');
425        $userInfo->total_cost_savings_summarized_monthly_by_flymsg_by_user = $cost_savings_summarized->implode('.   ');
426        $userInfo->total___of_characters_typed_monthly_by_flymsg_by_user = $characters_typed_summarized->implode('.   ');
427        $userInfo->total___of_times_flycut_is_used_summarized_monthly_by_user__count_ = $fly_cut_summarized->implode('.   ');
428        $userInfo->total___of_times_sentence_rewrite_is_used_summarized_monthly_by_user = $sentence_rewrite_summarized->implode('.   ');
429        $userInfo->total___of_times_paragraph_rewrite_is_used_summarized_monthly_by_user = $paragraph_rewrite_summarized->implode('.   ');
430        $userInfo->total___of_times_flyengage_is_used_summarized_monthly_by_user = $fly_engage_summarized->implode('.   ');
431        $userInfo->total___of_times_flyposts_is_used_summarized_monthly_by_user__count_ = $fly_post_summarized->implode('.   ');
432        $userInfo->total___of_times_flygrammar_is_used_summarized_monthly_by_user = $fly_grammar_actions_summarized->implode('.   ');
433        $userInfo->total___of_times_flygrammar_accepted_is_used_summarized_monthly_by_user = $fly_grammar_accepted_summarized->implode('.   ');
434        $userInfo->total___of_times_flygrammar_autocorrect_is_used_summarized_monthly_by_user = $fly_grammar_autocorrect_summarized->implode('.   ');
435        $userInfo->total___of_times_flygrammar_autocomplete_is_used_summarized_monthly_by_user = $fly_grammar_autocomplete_summarized->implode('.   ');
436
437        // Atualize os campos de totais absolutos
438        $userInfo->total___of_times_sentence_rewrite_used__count_ = $totals['sentence_rewrite_count'] ?? 0;
439        $userInfo->total___of_times_paragraph_rewrite_used__count_ = $totals['paragraph_rewrite_count'] ?? 0;
440        $userInfo->total___of_times_flyengage_used__count_ = $totals['flyengage_count'] ?? 0;
441        $userInfo->total___of_times_flyposts_used__count_ = $totals['flypost_count'] ?? 0;
442        $userInfo->total___of_times_flycut_used__count_ = $totals['flycut_count'] ?? 0;
443        $userInfo->total___of_times_flygrammar_is_used_count = $totals['fly_grammar_actions'] ?? 0;
444        $userInfo->total___of_times_flygrammar_accepted_is_used_count = $totals['fly_grammar_accepted'] ?? 0;
445        $userInfo->total___of_times_flygrammar_autocorrect_is_used_count = $totals['fly_grammar_autocorrect'] ?? 0;
446        $userInfo->total___of_times_flygrammar_autocomplete_is_used_count = $totals['fly_grammar_autocomplete'] ?? 0;
447        $userInfo->total_time_saved_by_flymsg_by_user = $totals['total_time_saved'] ?? 0;
448        $userInfo->total_cost_savings_by_flymsg_by_user = $totals['total_cost_savings'] ?? 0;
449        $userInfo->total___of_characters_typed_by_flymsg_by_user = $totals['total_characters_typed'] ?? 0;
450        $userInfo->number_of_flycuts_created_count = $totals['number_of_flycuts_created_count'] ?? 0;
451        $userInfo->number_of_flyplates_in_flycuts_count = $totals['number_of_flyplates_in_flycuts_count'] ?? 0;
452
453        $userInfo->save();
454    }
455
456    public function processUserUsage(User $user, bool $onlyUpdate = false): void
457    {
458        $startDate = $user->created_at->copy();
459
460        if ($startDate->lessThan(Carbon::parse('2022-01-01 00:00:00'))) {
461            $startDate = Carbon::parse('2022-01-01 00:00:00');
462        }
463
464        if ($onlyUpdate) {
465            $lastRegister = FlyMsgUserDailyUsage::where('user_id', $user->id)->orderBy('created_at', 'desc')->first();
466            if ($lastRegister) {
467                $startDate = $lastRegister->created_at->copy();
468            }
469        }
470
471        $endDate = now();
472
473        $user_id = $user->id;
474        $email_domain = strrchr($user->email, '@');
475        $user_status = $user->status ?? 'Active';
476        $hubspot_id = $user->hubspot_id;
477        $company_id = $user->company_id;
478
479        $group = CompanyGroup::find($user->company_group_id);
480        if (! empty($group?->parent_id)) {
481            $subgroup_id = $user->company_group_id;
482            $group_id = $group->parent_id;
483        } else {
484            $group_id = $user->company_group_id;
485            $subgroup_id = null;
486        }
487
488        $category = $company_id ? 'corporate' : 'individual';
489
490        // 1. Array associativo para todas as datas
491        $merged = [];
492
493        if ($startDate->lessThan(Carbon::parse('2023-02-01 00:00:00'))) {
494            // -------- HUBSPOT USAGE --------
495            $hubspotData = $this->getHubspotUsage($user_id); // igual ao anterior
496            foreach ($hubspotData as $month => $data) {
497                $formatted = ucwords(str_replace('_', ' ', $month)); // "April 2022"
498                $date = Carbon::createFromFormat('F Y', $formatted)->startOfMonth()->copy();
499                $daysInMonth = $date->daysInMonth;
500
501                for ($i = 1; $i <= $daysInMonth; $i++) {
502                    $dt = $date->copy()->day($i);
503                    $key = $dt->toDateString();
504                    if (! isset($merged[$key])) {
505                        $merged[$key] = [];
506                    }
507                    $merged[$key]['characters_typed'] = $data['characters_per_day'] ?? 0;
508                    $merged[$key]['cost_savings'] = $data['cost_per_day'] ?? 0;
509                    $merged[$key]['time_saved'] = $data['time_saved_per_day'] ?? 0;
510                    // Os outros campos virão depois
511                }
512            }
513        }
514
515        // -------- FLYCUT USAGE --------
516        $usages = FlyCutUsage::raw(function ($collection) use ($user_id, $startDate, $endDate) {
517            return $collection->aggregate([
518                ['$match' => [
519                    'user_id' => $user_id,
520                    'created_at' => [
521                        '$gte' => new UTCDateTime(strtotime($startDate->toDateString()) * 1000),
522                        '$lte' => new UTCDateTime(strtotime($endDate->toDateString()) * 1000),
523                    ],
524                ]],
525                ['$group' => [
526                    '_id' => [
527                        'year' => ['$year' => '$created_at'],
528                        'month' => ['$month' => '$created_at'],
529                        'day' => ['$dayOfMonth' => '$created_at'],
530                    ],
531                    'time_saved' => ['$sum' => '$time_saved'],
532                    'cost_savings' => ['$sum' => '$cost_saved'],
533                    'characters_typed' => ['$sum' => '$characters_saved'],
534                    'sentence_rewrite_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'sentence_rewrite']], 1, 0]]],
535                    'paragraph_rewrite_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'paragraph_rewrite']], 1, 0]]],
536                    'flyengage_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'flyengage']], 1, 0]]],
537                    'flypost_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'flypost']], 1, 0]]],
538                    'flycut_count' => ['$sum' => ['$cond' => [['$or' => [['$eq' => ['$feature', null]], ['$not' => ['$feature']]]], 1, 0]]],
539                ]],
540                ['$project' => [
541                    '_id' => 0,
542                    'year' => '$_id.year',
543                    'month' => '$_id.month',
544                    'day' => '$_id.day',
545                    'time_saved' => 1,
546                    'cost_savings' => 1,
547                    'characters_typed' => 1,
548                    'sentence_rewrite_count' => 1,
549                    'paragraph_rewrite_count' => 1,
550                    'flyengage_count' => 1,
551                    'flypost_count' => 1,
552                    'flycut_count' => 1,
553                ]],
554            ]);
555        });
556
557        foreach ($usages as $data) {
558            $dt = Carbon::createFromDate($data['year'], $data['month'], $data['day']);
559            $key = $dt->toDateString();
560            if (! isset($merged[$key])) {
561                $merged[$key] = [];
562            }
563            $merged[$key]['time_saved'] = $data['time_saved'] ?? 0;
564            $merged[$key]['cost_savings'] = $data['cost_savings'] ?? 0;
565            $merged[$key]['characters_typed'] = $data['characters_typed'] ?? 0;
566            $merged[$key]['sentence_rewrite_count'] = $data['sentence_rewrite_count'] ?? 0;
567            $merged[$key]['paragraph_rewrite_count'] = $data['paragraph_rewrite_count'] ?? 0;
568            $merged[$key]['flyengage_count'] = $data['flyengage_count'] ?? 0;
569            $merged[$key]['flypost_count'] = $data['flypost_count'] ?? 0;
570            $merged[$key]['flycut_count'] = $data['flycut_count'] ?? 0;
571        }
572
573        // -------- FLYCUT USAGE --------
574        $usages = FlyCutUsage::raw(function ($collection) use ($user_id, $startDate, $endDate) {
575            return $collection->aggregate([
576                ['$match' => [
577                    'user_id' => $user_id,
578                    'created_at' => [
579                        '$gte' => new UTCDateTime(strtotime($startDate->toDateString()) * 1000),
580                        '$lte' => new UTCDateTime(strtotime($endDate->toDateString()) * 1000),
581                    ],
582                ]],
583                ['$group' => [
584                    '_id' => [
585                        'year' => ['$year' => '$created_at'],
586                        'month' => ['$month' => '$created_at'],
587                        'day' => ['$dayOfMonth' => '$created_at'],
588                    ],
589                    'time_saved' => ['$sum' => '$time_saved'],
590                    'cost_savings' => ['$sum' => '$cost_saved'],
591                    'characters_typed' => ['$sum' => '$characters_saved'],
592                    'sentence_rewrite_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'sentence_rewrite']], 1, 0]]],
593                    'paragraph_rewrite_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'paragraph_rewrite']], 1, 0]]],
594                    'flyengage_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'flyengage']], 1, 0]]],
595                    'flypost_count' => ['$sum' => ['$cond' => [['$eq' => ['$feature', 'flypost']], 1, 0]]],
596                    'flycut_count' => ['$sum' => ['$cond' => [['$or' => [['$eq' => ['$feature', null]], ['$not' => ['$feature']]]], 1, 0]]],
597                ]],
598                ['$project' => [
599                    '_id' => 0,
600                    'year' => '$_id.year',
601                    'month' => '$_id.month',
602                    'day' => '$_id.day',
603                    'time_saved' => 1,
604                    'cost_savings' => 1,
605                    'characters_typed' => 1,
606                    'sentence_rewrite_count' => 1,
607                    'paragraph_rewrite_count' => 1,
608                    'flyengage_count' => 1,
609                    'flypost_count' => 1,
610                    'flycut_count' => 1,
611                ]],
612            ]);
613        });
614
615        foreach ($usages as $data) {
616            $dt = Carbon::createFromDate($data['year'], $data['month'], $data['day']);
617            $key = $dt->toDateString();
618            if (! isset($merged[$key])) {
619                $merged[$key] = [];
620            }
621            $merged[$key]['time_saved'] = $data['time_saved'] ?? 0;
622            $merged[$key]['cost_savings'] = $data['cost_savings'] ?? 0;
623            $merged[$key]['characters_typed'] = $data['characters_typed'] ?? 0;
624            $merged[$key]['sentence_rewrite_count'] = $data['sentence_rewrite_count'] ?? 0;
625            $merged[$key]['paragraph_rewrite_count'] = $data['paragraph_rewrite_count'] ?? 0;
626            $merged[$key]['flyengage_count'] = $data['flyengage_count'] ?? 0;
627            $merged[$key]['flypost_count'] = $data['flypost_count'] ?? 0;
628            $merged[$key]['flycut_count'] = $data['flycut_count'] ?? 0;
629        }
630
631        // -------- SHORTCUTS --------
632        $shortcuts = Shortcut::raw(function ($collection) use ($user_id, $startDate, $endDate) {
633            return $collection->aggregate([
634                ['$match' => [
635                    'user_id' => $user_id,
636                    'created_at' => [
637                        '$gte' => new UTCDateTime(strtotime($startDate->toDateString()) * 1000),
638                        '$lte' => new UTCDateTime(strtotime($endDate->toDateString()) * 1000),
639                    ],
640                ]],
641                ['$group' => [
642                    '_id' => [
643                        'year' => ['$year' => '$created_at'],
644                        'month' => ['$month' => '$created_at'],
645                        'day' => ['$dayOfMonth' => '$created_at'],
646                        'user_defined' => '$user_defined',
647                    ],
648                    'count' => ['$sum' => 1],
649                ]],
650                ['$project' => [
651                    '_id' => 0,
652                    'year' => '$_id.year',
653                    'month' => '$_id.month',
654                    'day' => '$_id.day',
655                    'user_defined' => '$_id.user_defined',
656                    'count' => 1,
657                ]],
658            ]);
659        });
660
661        foreach ($shortcuts as $data) {
662            $dt = Carbon::createFromDate($data['year'], $data['month'], $data['day']);
663            $key = $dt->toDateString();
664            if (! isset($merged[$key])) {
665                $merged[$key] = [];
666            }
667            $merged[$key]['flycuts_created'] = ($data['user_defined'] ?? false) ? $data['count'] : 0;
668            $merged[$key]['flyplates_added'] = (! ($data['user_defined'] ?? false)) ? $data['count'] : 0;
669        }
670
671        // -------- FLYGRAMMAR USAGE --------
672        $actionsUsage = FlyGrammarActions::raw(function ($collection) use ($user_id, $startDate, $endDate) {
673            return $collection->aggregate([
674                ['$match' => [
675                    'user_id' => $user_id,
676                    'created_at' => [
677                        '$gte' => new UTCDateTime(strtotime($startDate->toDateString()) * 1000),
678                        '$lte' => new UTCDateTime(strtotime($endDate->toDateString()) * 1000),
679                    ],
680                ]],
681                ['$group' => [
682                    '_id' => [
683                        'year' => ['$year' => '$created_at'],
684                        'month' => ['$month' => '$created_at'],
685                        'day' => ['$dayOfMonth' => '$created_at'],
686                    ],
687                    'time_saved' => ['$sum' => '$time_saved'],
688                    'cost_savings' => ['$sum' => '$cost_saved'],
689                    'characters_typed' => ['$sum' => '$characters_count'],
690                    'actions_count' => ['$sum' => 1],
691                    'actions_accepted_count' => ['$sum' => ['$cond' => [['$ne' => ['$action_type', 'autocorrect']], 1, 0]]],
692                    'actions_autocorrect_count' => ['$sum' => ['$cond' => [['$eq' => ['$action_type', 'autocorrect']], 1, 0]]],
693                ]],
694                ['$project' => [
695                    '_id' => 0,
696                    'year' => '$_id.year',
697                    'month' => '$_id.month',
698                    'day' => '$_id.day',
699                    'time_saved' => 1,
700                    'cost_savings' => 1,
701                    'characters_typed' => 1,
702                    'actions_count' => 1,
703                    'actions_accepted_count' => 1,
704                    'actions_autocorrect_count' => 1,
705                ]],
706            ]);
707        });
708
709        foreach ($actionsUsage as $data) {
710            $dt = Carbon::createFromDate($data['year'], $data['month'], $data['day']);
711            $key = $dt->toDateString();
712            if (! isset($merged[$key])) {
713                $merged[$key] = [];
714            }
715            $merged[$key]['time_saved'] = ($merged[$key]['time_saved'] ?? 0) + ($data['time_saved'] ?? 0);
716            $merged[$key]['cost_savings'] = ($merged[$key]['cost_savings'] ?? 0) + ($data['cost_savings'] ?? 0);
717            $merged[$key]['characters_typed'] = ($merged[$key]['characters_typed'] ?? 0) + ($data['characters_typed'] ?? 0);
718            $merged[$key]['fly_grammar_actions'] = $data['actions_count'] ?? 0;
719            $merged[$key]['fly_grammar_accepted'] = $data['actions_accepted_count'] ?? 0;
720            $merged[$key]['fly_grammar_autocorrect'] = $data['actions_autocorrect_count'] ?? 0;
721            $merged[$key]['fly_grammar_autocomplete'] = $data['actions_autocomplete_count'] ?? 0;
722        }
723
724        // -------- ÃšNICO BULK OP --------
725        if (! empty($merged)) {
726            FlyMsgUserDailyUsage::raw(function ($collection) use ($merged, $user_id, $email_domain, $user_status, $hubspot_id, $company_id, $group_id, $subgroup_id, $category) {
727                $bulkOps = [];
728                foreach ($merged as $key => $fields) {
729                    $dt = Carbon::parse($key); // key Ã© 'Y-m-d'
730                    // Preenche campos padrão para evitar campo unset/undefined
731                    $toUpdate = [
732                        'user_id' => $user_id,
733                        'year' => $dt->year,
734                        'month' => $dt->month,
735                        'day' => $dt->day,
736                        'email_domain' => $email_domain,
737                        'user_status' => $user_status,
738                        'hubspot_id' => $hubspot_id,
739                        'company_id' => $company_id,
740                        'group_id' => $group_id,
741                        'category' => $category,
742                        'created_at' => new UTCDateTime($dt->timestamp * 1000),
743                        'updated_at' => new UTCDateTime($dt->timestamp * 1000),
744                    ];
745
746                    if (! empty($subgroup_id)) {
747                        $toUpdate['subgroup_id'] = $subgroup_id;
748                    }
749
750                    $row = array_merge([
751                        'time_saved' => 0,
752                        'cost_savings' => 0,
753                        'characters_typed' => 0,
754                        'sentence_rewrite_count' => 0,
755                        'paragraph_rewrite_count' => 0,
756                        'flyengage_count' => 0,
757                        'flypost_count' => 0,
758                        'flycut_count' => 0,
759                        'flycuts_created' => 0,
760                        'flyplates_added' => 0,
761                        'fly_grammar_actions' => 0,
762                        'fly_grammar_accepted' => 0,
763                        'fly_grammar_autocorrect' => 0,
764                        'fly_grammar_autocomplete' => 0,
765                    ], $fields, $toUpdate);
766                    $bulkOps[] = [
767                        'updateOne' => [
768                            [
769                                'user_id' => $row['user_id'],
770                                'year' => $row['year'],
771                                'month' => $row['month'],
772                                'day' => $row['day'],
773                            ],
774                            ['$set' => $row],
775                            ['upsert' => true],
776                        ],
777                    ];
778                }
779
780                return $collection->bulkWrite($bulkOps);
781            });
782        }
783    }
784
785    private function parseMonth(int $month): string
786    {
787        return match ($month) {
788            1 => 'january',
789            2 => 'february',
790            3 => 'march',
791            4 => 'april',
792            5 => 'may',
793            6 => 'june',
794            7 => 'july',
795            8 => 'august',
796            9 => 'september',
797            10 => 'october',
798            11 => 'november',
799            default => 'december',
800        };
801    }
802
803    private function getHubspotUsage(string $user_id)
804    {
805        $allMonths = [
806            'october_2020',
807            'november_2020',
808            'december_2020',
809            'january_2021',
810            'february_2021',
811            'march_2021',
812            'april_2021',
813            'may_2021',
814            'june_2021',
815            'july_2021',
816            'august_2021',
817            'september_2021',
818            'october_2021',
819            'november_2021',
820            'december_2021',
821            'january_2022',
822            'february_2022',
823            'march_2022',
824            'april_2022',
825            'may_2022',
826            'june_2022',
827            'july_2022',
828            'august_2022',
829            'september_2022',
830            'october_2022',
831            'november_2022',
832            'december_2022',
833            'january_2023',
834        ];
835
836        $hubspotQuery = HubspotProperties::raw(function ($collection) use ($user_id, $allMonths) {
837            $fieldsProject = [
838                'flymsg_id' => 1,
839            ];
840
841            foreach ($allMonths as $month) {
842                $fieldsProject['of_characters_typed___'.$month] = 1;
843                $fieldsProject['total_cost_savings___'.$month] = 1;
844                $fieldsProject['total_time_saved___'.$month] = 1;
845            }
846
847            return $collection->aggregate([
848                ['$match' => [
849                    'flymsg_id' => $user_id,
850                ]],
851                ['$project' => $fieldsProject],
852            ]);
853        });
854
855        $doc = $hubspotQuery[0] ?? null;
856
857        $monthlyData = [];
858
859        $user = User::find($user_id);
860
861        $wagePerHour = $user->setting?->wage_per_hour ?? FlyCutUsage::WAGE_PER_HOUR;
862        $userWordPerMinute = $user->setting?->words_per_minute ?? FlyCutUsage::WORDS_PER_MINUTE;
863        $characterPerHour = $userWordPerMinute * 300;
864
865        if ($doc) {
866            foreach ($allMonths as $month) {
867                $characters = isset($doc['of_characters_typed___'.$month]) ? (int) $doc['of_characters_typed___'.$month] : 0;
868                if ($characters <= 0) {
869                    continue;
870                }
871                // $time = isset($doc['total_time_saved___'.$month]) ? (int)$doc['total_time_saved___'.$month] : 0;
872                $time = round($characters / $characterPerHour, 8);
873                // $cost = isset($doc['total_cost_savings___'.$month]) ? (float)$doc['total_cost_savings___'.$month] : 0;
874                $cost = round($time * $wagePerHour, 8);
875                $daysInMonth = cal_days_in_month(
876                    CAL_GREGORIAN,
877                    Carbon::createFromFormat('F Y', ucwords(str_replace('_', ' ', $month)))->startOfMonth()->format('m'),
878                    Carbon::createFromFormat('F Y', ucwords(str_replace('_', ' ', $month)))->startOfMonth()->format('Y')
879                );
880
881                $monthlyData[$month] = [
882                    'characters' => $characters,
883                    'characters_per_day' => (int) round($daysInMonth ? ($characters / $daysInMonth) : 0),
884                    'cost_savings' => $cost,
885                    'cost_per_day' => $daysInMonth ? ($cost / $daysInMonth) : 0,
886                    'time_saved' => $time,
887                    'time_saved_per_day' => $daysInMonth ? ($time / $daysInMonth) : 0,
888                ];
889            }
890        }
891
892        return $monthlyData;
893    }
894}