package com.taf.waf import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.taf.waf.db.PendingOhsIncident import com.taf.waf.db.PendingSafetyIncident import com.taf.waf.db.WafDatabase import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody import okhttp3.OkHttpClient import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.io.File class SyncIncidentsWorker(appContext: Context, params: WorkerParameters) : CoroutineWorker(appContext, params) { private val db = WafDatabase.get(appContext) private val gson = Gson() override suspend fun doWork(): Result { var successCount = 0 val ohsList = db.pendingOhsIncidentDao().getAll() for (item in ohsList) { if (submitOhs(item)) { db.pendingOhsIncidentDao().delete(item) successCount++ } } val safetyList = db.pendingSafetyIncidentDao().getAll() for (item in safetyList) { if (submitSafety(item)) { db.pendingSafetyIncidentDao().delete(item) successCount++ } } if (successCount > 0) { notifySuccess(successCount) } return Result.success() } private fun api(token: String): IncidentApiService { val client = OkHttpClient.Builder() .addInterceptor { chain -> val req = chain.request().newBuilder() .addHeader("Authorization", "Bearer $token") .build() chain.proceed(req) } .build() return Retrofit.Builder() .baseUrl(com.taf.ohs.ApiConfig.BASE_URL + "api/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() .create(IncidentApiService::class.java) } private fun buildParts(paths: List): List = paths.mapNotNull { path -> val file = File(path) if (file.exists()) { val body = file.asRequestBody("application/octet-stream".toMediaTypeOrNull()) MultipartBody.Part.createFormData("files[]", file.name, body) } else null } private suspend fun submitOhs(item: PendingOhsIncident): Boolean { return try { val service = api(item.token) val dataBody = item.payload.toRequestBody("application/json".toMediaType()) val paths: List = item.attachments?.let { gson.fromJson(it, object : TypeToken>() {}.type) } ?: emptyList() service.submitOhsIncident(dataBody, buildParts(paths)) true } catch (e: Exception) { false } } private suspend fun submitSafety(item: PendingSafetyIncident): Boolean { return try { val service = api(item.token) val dataBody = item.payload.toRequestBody("application/json".toMediaType()) val paths: List = item.attachments?.let { gson.fromJson(it, object : TypeToken>() {}.type) } ?: emptyList() service.submitSafetyIncident(dataBody, buildParts(paths)) true } catch (e: Exception) { false } } private fun notifySuccess(count: Int) { val channelId = "incident_sync" val manager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel(channelId, "Incident Sync", NotificationManager.IMPORTANCE_DEFAULT) manager.createNotificationChannel(channel) } val notification = NotificationCompat.Builder(applicationContext, channelId) .setSmallIcon(android.R.drawable.stat_notify_sync) .setContentTitle("Incidents Synced") .setContentText("$count incidents uploaded") .build() NotificationManagerCompat.from(applicationContext).notify(1001, notification) } }