package com.taf.waf import android.content.Context import android.content.SharedPreferences import androidx.work.Constraints import androidx.work.ExistingWorkPolicy import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import com.google.gson.Gson 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 okhttp3.JavaNetCookieJar import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.io.File import java.net.CookieManager import java.net.CookiePolicy class IncidentRepository(context: Context) { private val db = WafDatabase.get(context) private val prefs: SharedPreferences = context.getSharedPreferences("auth", Context.MODE_PRIVATE) private val gson = Gson() private val workManager = WorkManager.getInstance(context) private val api: IncidentApiService init { val logging = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val cookieManager = CookieManager().apply { setCookiePolicy(CookiePolicy.ACCEPT_ALL) } val client = OkHttpClient.Builder() .cookieJar(JavaNetCookieJar(cookieManager)) .addInterceptor(logging) .addInterceptor { chain -> val token = prefs.getString("token", null) val req = chain.request().newBuilder() if (!token.isNullOrEmpty()) { req.addHeader("Authorization", "Bearer $token") } chain.proceed(req.build()) } .build() api = Retrofit.Builder() .baseUrl(com.taf.ohs.ApiConfig.BASE_URL + "api/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() .create(IncidentApiService::class.java) } suspend fun submitOhsIncident(data: Map, attachments: List): Boolean { return try { api.submitOhsIncident(buildDataBody(data), buildParts(attachments)) true } catch (e: Exception) { savePendingOhs(data, attachments) enqueueSync() false } } suspend fun submitSafetyIncident(data: Map, attachments: List): Boolean { return try { api.submitSafetyIncident(buildDataBody(data), buildParts(attachments)) true } catch (e: Exception) { savePendingSafety(data, attachments) enqueueSync() false } } private fun buildDataBody(data: Map) = gson.toJson(data).toRequestBody("application/json".toMediaType()) private fun buildParts(files: List): List = files.map { file -> val body = file.asRequestBody("application/octet-stream".toMediaTypeOrNull()) MultipartBody.Part.createFormData("files[]", file.name, body) } private suspend fun savePendingOhs(data: Map, attachments: List) { val token = prefs.getString("token", "") ?: "" val paths = attachments.map { it.absolutePath } db.pendingOhsIncidentDao().insert( PendingOhsIncident( payload = gson.toJson(data), token = token, attachments = gson.toJson(paths) ) ) } private suspend fun savePendingSafety(data: Map, attachments: List) { val token = prefs.getString("token", "") ?: "" val paths = attachments.map { it.absolutePath } db.pendingSafetyIncidentDao().insert( PendingSafetyIncident( payload = gson.toJson(data), token = token, attachments = gson.toJson(paths) ) ) } private fun enqueueSync() { val work = OneTimeWorkRequestBuilder() .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() ) .build() workManager.enqueueUniqueWork( "sync_incidents", ExistingWorkPolicy.KEEP, work ) } }