import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/network/api_client.dart'; import '../models/admin_driver.dart'; import '../models/admin_incident.dart'; import '../models/admin_route.dart'; import '../models/admin_unit.dart'; import '../models/admin_user.dart'; final adminServiceProvider = Provider((ref) { return AdminService(ref.read(apiClientProvider)); }); class AdminService { AdminService(this._dio); final Dio _dio; // ── Users ─────────────────────────────────────────────────────────────────── Future> listUsers() async { final res = await _dio.get>('/admin/users'); return (res.data ?? []) .whereType() .map((e) => AdminUserModel.fromJson(Map.from(e))) .toList(); } Future createUser({ required String name, required String password, String? email, String? phone, String role = 'citizen', }) async { final res = await _dio.post>( '/admin/users', data: { 'name': name, 'password': password, if (email != null && email.isNotEmpty) 'email': email, if (phone != null && phone.isNotEmpty) 'phone': phone, 'role': role, }, ); return AdminUserModel.fromJson(res.data!); } Future updateUser( String id, { String? name, String? email, String? role, }) async { final res = await _dio.patch>( '/admin/users/$id', data: { if (name != null) 'name': name, if (email != null) 'email': email, if (role != null) 'role': role, }, ); return AdminUserModel.fromJson(res.data!); } Future deleteUser(String id) async { await _dio.delete('/admin/users/$id'); } // ── Routes ────────────────────────────────────────────────────────────────── Future> listRoutes() async { final res = await _dio.get>('/admin/routes'); return (res.data ?? []) .whereType() .map((e) => AdminRouteModel.fromJson(Map.from(e))) .toList(); } Future createRoute({ required String id, String? name, int? truckId, String? turno, String? status, }) async { final res = await _dio.post>( '/admin/routes', data: { 'id': id, if (name != null) 'name': name, if (truckId != null) 'truck_id': truckId, if (turno != null) 'turno': turno, if (status != null) 'status': status, }, ); return AdminRouteModel.fromJson(res.data!); } Future updateRoute( String id, { String? name, int? truckId, String? turno, String? status, }) async { final res = await _dio.patch>( '/admin/routes/$id', data: { if (name != null) 'name': name, if (truckId != null) 'truck_id': truckId, if (turno != null) 'turno': turno, if (status != null) 'status': status, }, ); return AdminRouteModel.fromJson(res.data!); } Future deleteRoute(String id) async { await _dio.delete('/admin/routes/$id'); } // ── Units ─────────────────────────────────────────────────────────────────── Future> listUnits() async { final res = await _dio.get>('/admin/units'); return (res.data ?? []) .whereType() .map((e) => AdminUnitModel.fromJson(Map.from(e))) .toList(); } Future createUnit({ required int id, String? plate, String status = 'active', }) async { final res = await _dio.post>( '/admin/units', data: {'id': id, if (plate != null) 'plate': plate, 'status': status}, ); return AdminUnitModel.fromJson(res.data!); } Future updateUnit( int id, { String? plate, String? status, }) async { final res = await _dio.patch>( '/admin/units/$id', data: { if (plate != null) 'plate': plate, if (status != null) 'status': status, }, ); return AdminUnitModel.fromJson(res.data!); } Future deleteUnit(int id) async { await _dio.delete('/admin/units/$id'); } // ── Drivers ───────────────────────────────────────────────────────────────── Future> listDrivers() async { final res = await _dio.get>('/admin/drivers'); return (res.data ?? []) .whereType() .map((e) => AdminDriverModel.fromJson(Map.from(e))) .toList(); } Future createDriver({ required String userId, int? unitId, }) async { final res = await _dio.post>( '/admin/drivers', data: {'user_id': userId, if (unitId != null) 'unit_id': unitId}, ); return AdminDriverModel.fromJson(res.data!); } Future updateDriver(String id, {int? unitId}) async { final res = await _dio.patch>( '/admin/drivers/$id', data: {if (unitId != null) 'unit_id': unitId}, ); return AdminDriverModel.fromJson(res.data!); } Future deleteDriver(String id) async { await _dio.delete('/admin/drivers/$id'); } // ── Incidents ──────────────────────────────────────────────────────────────── Future> listIncidentsByUnit(int unitId) async { final res = await _dio.get>('/admin/units/$unitId/incidents'); return (res.data ?? []) .whereType() .map((e) => AdminIncidentModel.fromJson(Map.from(e))) .toList(); } Future createIncident({ required int unitId, required String type, String? description, }) async { final res = await _dio.post>( '/admin/units/$unitId/incidents', data: { 'unit_id': unitId, 'type': type, if (description != null && description.isNotEmpty) 'description': description, }, ); return AdminIncidentModel.fromJson(res.data!); } // ── Simulación ────────────────────────────────────────────────────────────── /// Avanza una vez la simulación (`positionId += 1` en todas las rutas) y /// dispara los push FCM correspondientes. Devuelve los eventos disparados. Future>> simulationTick() async { final res = await _dio.post>('/simulation/tick'); final events = (res.data?['events'] as List?) ?? const []; return events .whereType() .map((e) => Map.from(e)) .toList(); } }