syncPendingUpdates function

Future<void> syncPendingUpdates()

Sincroniza los registros que quedaron pendientes en la base local.

Implementation

Future<void> syncPendingUpdates() async {
  final dbHelper = DatabaseHelper();

  // 1) Mostrar todos los locales en consola (debug)
  final allIndividuos = await dbHelper.getAllIndividuos();
  print('Todos los individuos en la base de datos local:');
  print(allIndividuos);

  // 2) Obtener la lista de pendientes
  final pendingUpdates = await dbHelper.getPendingUpdates();
  print('Total de pendientes a sincronizar: ${pendingUpdates.length}');

  for (var update in pendingUpdates) {
    final dataJson = update['data'] as String;
    final decoded = jsonDecode(dataJson) as Map<String, dynamic>;

    // Extraer el ID alfanumérico
    final id = decoded['id'] as String;
    print('Procesando pendiente con ID: $id');
    print('Datos obtenidos de la tabla de pendientes:');
    print(decoded);

    // 3) Obtener el individuo original de la base local
    final originalIndividuo = await dbHelper.getIndividuoById(id);
    if (originalIndividuo == null) {
      print('No se encontró el individuo original para el ID: $id');
      await dbHelper.deletePendingUpdate(update['id']);
      continue;
    }

    // 4) Detectar qué campos cambiaron (decoded vs originalIndividuo)
    final changedFields = <String, dynamic>{};
    decoded.forEach((key, value) {
      if (value != originalIndividuo[key]) {
        changedFields[key] = value;
      }
    });

    // Si no hay cambios reales, eliminar el pendiente
    if (changedFields.isEmpty) {
      print('No hay cambios para el ID: $id');
      await dbHelper.deletePendingUpdate(update['id']);
      continue;
    }

    // 5) Validar / heredar cod_especie_id:

    if (changedFields.containsKey('cod_especie_code_specie')) {
      // Si el usuario modificó el código
      final newCode = changedFields['cod_especie_code_specie'].toString();
      final species = await dbHelper.getSpeciesByCode(newCode);
      if (species == null) {
        print('Código de especie inválido en pendiente para ID: $id');
        // No eliminamos el pendiente; queda para que el usuario corrija
        continue;
      }
      changedFields['cod_especie_id'] = species['code_specie'];
    } else {
      // Si no cambió el código, intentar heredar cod_especie_id del original
      if (originalIndividuo['cod_especie_id'] != null) {
        changedFields['cod_especie_id'] = originalIndividuo['cod_especie_id'];
      } else {
        // Si en original solo existía cod_especie_code_specie, buscar su ID
        final originalCode =
            originalIndividuo['cod_especie_code_specie']?.toString();
        if (originalCode != null && originalCode.isNotEmpty) {
          final species = await dbHelper.getSpeciesByCode(originalCode);
          if (species != null) {
            changedFields['cod_especie_id'] = species['code_specie'];
          }
        }
      }
    }

    // 6) Preparar JSON para la API
    final apiData = _prepareApiData(changedFields, originalIndividuo);

    print('Datos a enviar a la API para el ID $id:');
    print(apiData);

    // 7) Enviar la petición PUT
    final url = 'https://api.corpoamazonia.gov.co/candidates/trees/$id';
    String? accessToken = await tokenManager.getToken();
    if (accessToken == null) {
      print(
          'No se pudo obtener un token de acceso válido para sincronizar pendientes');
      continue;
    }

    try {
      final client = http.Client();
      final response = await client.put(
        Uri.parse(url),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $accessToken',
          'Accept': 'application/json',
        },
        body: jsonEncode(apiData),
      );

      print('Respuesta del servidor: ${response.statusCode}');
      print('Cuerpo de la respuesta: ${response.body}');

      if (response.statusCode == 200) {
        print('Pendiente enviado con éxito: $id');
        await notificationHelper.sendNotification('Sincronización Exitosa',
            'Pendiente enviado con éxito para ID: $id.');
        await dbHelper.deletePendingUpdate(update['id']);
      } else {
        print('Error al enviar pendiente: ${response.statusCode}');
        await notificationHelper.sendNotification('Error de Sincronización',
            'Error al enviar pendiente para ID $id: ${response.statusCode}.');
        // No borramos el pendiente: se reintentará más tarde
      }
      client.close();
    } catch (error) {
      print('Error al enviar pendiente: $error');
      await notificationHelper.sendNotification('Error de Sincronización',
          'Error al enviar pendiente para ID $id: $error.');
      // Se conserva en pendientes para reintentar
    }
  }
}