import '../../../../core/network/api_client.dart'; import '../models/dashboard_metrics_model.dart'; import '../models/doctor_info_model.dart'; import '../models/patient_summary_model.dart'; class DashboardService { final ApiClient apiClient; DashboardService({ApiClient? client}) : apiClient = client ?? ApiClient(); String _formatTwoDigits(int n) => n.toString().padLeft(2, '0'); Future getDoctorConfig() async { try { final response = await apiClient.dio.get('/items/configuracion'); if (response.statusCode == 200 && response.data != null) { final data = response.data['data'] as Map; return DoctorInfoModel.fromJson(data); } return const DoctorInfoModel( nombreDoctor: 'Dr. Luis A. Castro Sosa', especialidad: 'Cirujano Urólogo', descripEspecialidad: '', descripGeneral: '', ); } catch (_) { return const DoctorInfoModel( nombreDoctor: 'Dr. Luis A. Castro Sosa', especialidad: 'Cirujano Urólogo', descripEspecialidad: '', descripGeneral: '', ); } } Future getDashboardMetrics() async { try { final now = DateTime.now(); final day = _formatTwoDigits(now.day); final month = _formatTwoDigits(now.month); final year = now.year.toString(); final dmy = '$day/$month/$year'; final iso = '$year-$month-$day'; // Consultas concurrentes optimizadas a Directus final results = await Future.wait([ // 0: Desglose por sexo apiClient.dio.get('/items/pacientes?aggregate[count]=*&groupBy[]=sexo'), // 1: Citas para hoy (condición estricta: fec_proxcita igual a la fecha del día actual) apiClient.dio.get( '/items/pacientes?aggregate[count]=*&filter[_or][0][fec_proxcita][_eq]=$dmy&filter[_or][1][fec_proxcita][_starts_with]=$dmy&filter[_or][2][fec_proxcita][_starts_with]=$iso', ), // 2: Pacientes nuevos registrados hoy apiClient.dio.get( '/items/pacientes?aggregate[count]=*&filter[_or][0][fec_reg][_contains]=$dmy&filter[_or][1][fec_reg][_contains]=$iso', ), // 3: Pacientes consultados hoy apiClient.dio.get( '/items/pacientes?aggregate[count]=*&filter[_or][0][fec_ultcon][_contains]=$dmy&filter[_or][1][fec_ultcon][_contains]=$iso', ), // 4: Total de pacientes apiClient.dio.get('/items/pacientes?aggregate[count]=*'), ]); int masc = 11078; int fem = 2634; int citasHoy = 0; int nuevosHoy = 0; int consultadosHoy = 0; int total = 13712; // 0. Desglose por sexo if (results[0].statusCode == 200 && results[0].data != null) { final sexoData = results[0].data['data'] as List? ?? []; for (final item in sexoData) { final s = item['sexo']?.toString().toLowerCase() ?? ''; final count = int.tryParse(item['count'].toString()) ?? 0; if (s.contains('masc')) masc = count; if (s.contains('fem')) fem = count; } } // 1. Citas para hoy if (results[1].statusCode == 200 && results[1].data != null) { final data = results[1].data['data'] as List? ?? []; if (data.isNotEmpty) { citasHoy = int.tryParse(data[0]['count'].toString()) ?? 0; } } // 2. Nuevos hoy if (results[2].statusCode == 200 && results[2].data != null) { final data = results[2].data['data'] as List? ?? []; if (data.isNotEmpty) { nuevosHoy = int.tryParse(data[0]['count'].toString()) ?? 0; } } // 3. Consultados hoy if (results[3].statusCode == 200 && results[3].data != null) { final data = results[3].data['data'] as List? ?? []; if (data.isNotEmpty) { consultadosHoy = int.tryParse(data[0]['count'].toString()) ?? 0; } } // 4. Total pacientes if (results[4].statusCode == 200 && results[4].data != null) { final data = results[4].data['data'] as List? ?? []; if (data.isNotEmpty) { total = int.tryParse(data[0]['count'].toString()) ?? 13712; } } return DashboardMetricsModel( nuevosPacientes: nuevosHoy, consultadosHoy: consultadosHoy, citasHoy: citasHoy, pacientesMasculinos: masc, pacientesFemeninos: fem, totalPacientes: total, ); } catch (_) { return const DashboardMetricsModel(); } } Future> getRecentPatients({int limit = 5}) async { try { final response = await apiClient.dio.get( '/items/pacientes?sort=-id&limit=$limit&fields=id,nombre,apellido,cedula,telefono,fec_reg,fec_proxcita,seguro,mot_cons,estado_espera', ); if (response.statusCode == 200 && response.data != null) { final data = response.data['data'] as List? ?? []; return data .map((item) => PatientSummaryModel.fromJson(item as Map)) .toList(); } return []; } catch (_) { return []; } } Future> getAppointmentsByDate(DateTime date, {int limit = 100}) async { try { final day = _formatTwoDigits(date.day); final month = _formatTwoDigits(date.month); final year = date.year.toString(); final dmy = '$day/$month/$year'; final iso = '$year-$month-$day'; final response = await apiClient.dio.get( '/items/pacientes?filter[_or][0][fec_proxcita][_eq]=$dmy&filter[_or][1][fec_proxcita][_starts_with]=$dmy&filter[_or][2][fec_proxcita][_starts_with]=$iso&sort=-id&limit=$limit&fields=id,nombre,apellido,cedula,telefono,fec_proxcita,mot_cons,estado_espera', ); final data = response.data?['data'] as List? ?? []; return data .map((item) => PatientSummaryModel.fromJson(item as Map)) .toList(); } catch (_) { return []; } } Future> getTodayAppointments({int limit = 50}) async { return getAppointmentsByDate(DateTime.now(), limit: limit); } Future updatePatientWaitingStatus(int patientId, String nuevoEstado) async { try { final response = await apiClient.dio.patch( '/items/pacientes/$patientId', data: {'estado_espera': nuevoEstado}, ); return response.statusCode == 200; } catch (_) { return false; } } }