import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:siro_driver/constant/box_name.dart'; import 'package:siro_driver/constant/links.dart'; import 'package:siro_driver/controller/functions/crud.dart'; import 'package:siro_driver/models/model/driver/rides_summary_model.dart'; import '../../../main.dart'; class StatisticsController extends GetxController { bool isLoading = false; // ═══ Weekly Data ═══ List weeklyStats = []; double weeklyEarnings = 0; int weeklyTrips = 0; double weeklyHours = 0; // ═══ Monthly Data ═══ List monthlyEarnings = []; List monthlyRides = []; List monthlyDuration = []; double monthlyTotalEarnings = 0; int monthlyTotalTrips = 0; double monthlyTotalHours = 0; String bestDay = '--'; double bestDayEarnings = 0; // ═══ Tab State ═══ int selectedTab = 0; // 0=weekly, 1=monthly @override void onInit() { super.onInit(); reloadData(); } void changeTab(int tab) { selectedTab = tab; update(); } // ═══════ جلب البيانات الأسبوعية ═══════ Future fetchWeeklyData() async { isLoading = true; update(); try { var res = await CRUD().get( link: AppLink.getWeeklyAggregate, payload: { 'driver_id': box.read(BoxName.driverID).toString(), }, ); if (res != null && res != 'failure') { box.write('stats_weekly_cache', res); var data = jsonDecode(res); if (data['message'] is List) { weeklyStats = (data['message'] as List) .map((e) => DayStat.fromJson(e)) .toList(); weeklyEarnings = weeklyStats.fold(0, (s, d) => s + d.earnings); weeklyTrips = weeklyStats.fold(0, (s, d) => s + d.trips); weeklyHours = weeklyStats.fold(0, (s, d) => s + d.hours); } } } catch (e) { debugPrint('❌ [Stats] Weekly fetch error: $e'); // Fallback: generate from local data _generateLocalWeeklyData(); } isLoading = false; update(); } // ═══════ جلب البيانات الشهرية ═══════ Future fetchMonthlyData() async { try { // 1. أرباح شهرية var earningsRes = await CRUD().getWallet( link: AppLink.getAllPaymentFromRide, payload: {'driverID': box.read(BoxName.driverID).toString()}, ); if (earningsRes != null && earningsRes != 'failure') { box.write('stats_monthly_earnings_cache', earningsRes); var data = jsonDecode(earningsRes); if (data['message'] is List) { monthlyEarnings = (data['message'] as List) .map((e) => MonthlyPriceDriverModel.fromJson(e)) .toList(); monthlyTotalEarnings = monthlyEarnings.fold(0, (s, d) => s + d.pricePerDay); // أفضل يوم if (monthlyEarnings.isNotEmpty) { var best = monthlyEarnings .reduce((a, b) => a.pricePerDay > b.pricePerDay ? a : b); bestDay = best.day.toString(); bestDayEarnings = best.pricePerDay; } } } // 2. رحلات شهرية var ridesRes = await CRUD().get( link: AppLink.getRidesDriverByDay, payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); if (ridesRes != null && ridesRes != 'failure') { box.write('stats_monthly_rides_cache', ridesRes); var data = jsonDecode(ridesRes); if (data['message'] is List) { monthlyRides = (data['message'] as List) .map((e) => MonthlyRideModel.fromJson(e)) .toList(); monthlyTotalTrips = monthlyRides.fold(0, (s, d) => s + d.countRide); } } // 3. ساعات شهرية var durationRes = await CRUD().get( link: AppLink.getTotalDriverDuration, payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); if (durationRes != null && durationRes != 'failure') { box.write('stats_monthly_duration_cache', durationRes); var data = jsonDecode(durationRes); if (data['message'] is List) { monthlyDuration = (data['message'] as List) .map((e) => MonthlyDataModel.fromJson(e)) .toList(); monthlyTotalHours = monthlyDuration.fold(0, (s, d) => s + d.totalDuration.toDouble()); } } } catch (e) { debugPrint('❌ [Stats] Monthly fetch error: $e'); } update(); } void _generateLocalWeeklyData() { // Fallback بيانات محلية عند عدم توفر الـ API final now = DateTime.now(); weeklyStats = List.generate(7, (i) { final day = now.subtract(Duration(days: 6 - i)); return DayStat( date: day, dayName: _getDayName(day.weekday), earnings: 0, trips: 0, hours: 0, ); }); } String _getDayName(int weekday) { const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; return days[weekday - 1]; } bool _isFetching = false; Future reloadData({bool force = false}) async { if (_isFetching) return; _isFetching = true; // التحقق من التخزين المؤقت (3 ساعات) String? lastFetchStr = box.read('stats_last_fetch'); if (!force && lastFetchStr != null) { try { DateTime lastFetch = DateTime.parse(lastFetchStr); if (DateTime.now().difference(lastFetch).inHours < 3) { debugPrint('ℹ️ [Statistics] Loading cached statistics (last fetch: $lastFetchStr)'); // تحميل الكاش الأسبوعي String? weeklyCache = box.read('stats_weekly_cache'); if (weeklyCache != null) { var data = jsonDecode(weeklyCache); if (data['message'] is List) { weeklyStats = (data['message'] as List) .map((e) => DayStat.fromJson(e)) .toList(); weeklyEarnings = weeklyStats.fold(0, (s, d) => s + d.earnings); weeklyTrips = weeklyStats.fold(0, (s, d) => s + d.trips); weeklyHours = weeklyStats.fold(0, (s, d) => s + d.hours); } } // تحميل الكاش الشهري (الأرباح) String? earningsCache = box.read('stats_monthly_earnings_cache'); if (earningsCache != null) { var data = jsonDecode(earningsCache); if (data['message'] is List) { monthlyEarnings = (data['message'] as List) .map((e) => MonthlyPriceDriverModel.fromJson(e)) .toList(); monthlyTotalEarnings = monthlyEarnings.fold(0, (s, d) => s + d.pricePerDay); if (monthlyEarnings.isNotEmpty) { var best = monthlyEarnings .reduce((a, b) => a.pricePerDay > b.pricePerDay ? a : b); bestDay = best.day.toString(); bestDayEarnings = best.pricePerDay; } } } // تحميل الكاش الشهري (الرحلات) String? ridesCache = box.read('stats_monthly_rides_cache'); if (ridesCache != null) { var data = jsonDecode(ridesCache); if (data['message'] is List) { monthlyRides = (data['message'] as List) .map((e) => MonthlyRideModel.fromJson(e)) .toList(); monthlyTotalTrips = monthlyRides.fold(0, (s, d) => s + d.countRide); } } // تحميل الكاش الشهري (المدد) String? durationCache = box.read('stats_monthly_duration_cache'); if (durationCache != null) { var data = jsonDecode(durationCache); if (data['message'] is List) { monthlyDuration = (data['message'] as List) .map((e) => MonthlyDataModel.fromJson(e)) .toList(); monthlyTotalHours = monthlyDuration.fold(0, (s, d) => s + d.totalDuration.toDouble()); } } _isFetching = false; update(); return; } } catch (e) { debugPrint('⚠️ [Statistics] Failed to load cached statistics: $e'); } } isLoading = true; update(); try { debugPrint('📊 [Statistics] Reloading data from server...'); await fetchWeeklyData(); await fetchMonthlyData(); box.write('stats_last_fetch', DateTime.now().toIso8601String()); debugPrint('📊 [Statistics] Data reload complete.'); } catch (e) { debugPrint('❌ [Statistics] Error reloading data: $e'); } finally { _isFetching = false; isLoading = false; update(); } } } // ═══════ نموذج إحصائية اليوم ═══════ class DayStat { final DateTime date; final String dayName; final double earnings; final int trips; final double hours; DayStat({ required this.date, required this.dayName, required this.earnings, required this.trips, required this.hours, }); factory DayStat.fromJson(Map json) { final date = DateTime.tryParse(json['day']?.toString() ?? '') ?? DateTime.now(); const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; return DayStat( date: date, dayName: dayNames[date.weekday - 1], earnings: double.tryParse(json['earnings']?.toString() ?? '0') ?? 0, trips: int.tryParse(json['trips']?.toString() ?? '0') ?? 0, hours: double.tryParse(json['hours']?.toString() ?? '0') ?? 0, ); } }