package com.za.offline

import android.content.Intent
import android.provider.Settings
import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import com.alibaba.fastjson.JSONObject
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.GeocodeSearch.OnGeocodeSearchListener
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.ToastUtils
import com.za.bean.request.SaveEleOrderRequest
import com.za.bean.request.TaskFinishRequest
import com.za.bean.request.TaskFinishResponse
import com.za.bean.request.UpdateTaskBean
import com.za.bean.request.UpdateTaskRequest
import com.za.common.GlobalData
import com.za.common.log.LogUtil
import com.za.ext.toJson
import com.za.net.BaseObserver
import com.za.net.CommonMethod
import com.za.net.RetrofitHelper
import com.za.room.RoomHelper
import com.za.water_marker.PhotoMarkerManager
import com.za.water_marker.bean.PhotoMarkerInfo
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import java.io.File

interface IOfflineListener {
	fun start()
	fun stop()
	fun uploadSuccess()
	fun uploadFailure(msg : String?)
	fun currentTask(offlineUpdateTaskBean : OfflineUpdateTaskBean)
}

object OfflineManager {
	private var isUploading = false
	private var uploadDispose : Disposable? = null
	private var offlineListener : IOfflineListener? = null
	private var currentTaskId : Int? = null

	fun addOfflineListener(offlineListener : IOfflineListener) {
		this.offlineListener = offlineListener
	}


	fun start(taskId : Int?) {
		if (checkOfflineIsComplete(taskId)) {
			return
		}
		if (currentTaskId != null && taskId == currentTaskId && isUploading) {
			return
		}

		if (! Settings.canDrawOverlays(GlobalData.application)) {
			openSystemAlertPermissionDialog()
			return
		}

		stop()
		OfflineService.addListener()
		offlineListener?.start()
		uploadDispose = Observable.interval(0, 5, java.util.concurrent.TimeUnit.SECONDS)
			.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe {
				if (! isUploading) {
					val list =
						RoomHelper.db?.offlineTaskDao()?.getOfflineTaskFromTaskId(taskId ?: 0)
					if (list.isNullOrEmpty()) {
						LogUtil.print("离线任务", "离线任务为空!!")
						stop()
						ToastUtils.showLong("离线任务上传完成")
						return@subscribe
					}
					doUpload(list[0])
				}
			}
	}

	private fun stop() {
		uploadDispose?.dispose()
		uploadDispose = null
		isUploading = false
		currentTaskId = null
		offlineListener?.stop()
		offlineListener = null
	}


	private fun checkOfflineIsComplete(taskId : Int?) : Boolean {
		val list = RoomHelper.db?.offlineTaskDao()?.getOfflineTaskFromTaskId(taskId ?: 0)
		LogUtil.print("离线任务列表", "${list.toJson()}")
		return list.isNullOrEmpty()
	}

	private fun doUpload(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		offlineListener?.currentTask(offlineUpdateTaskBean)
		currentTaskId = offlineUpdateTaskBean.taskId
		when (offlineUpdateTaskBean.offlineType) {
			1 -> uploadTask(offlineUpdateTaskBean)
			2 -> uploadOrderImage(offlineUpdateTaskBean)
			3 -> uploadEleWorkOrder(offlineUpdateTaskBean)
			4 -> uploadEleDamageImage(offlineUpdateTaskBean)
			5 -> uploadCustomerSignImage(offlineUpdateTaskBean)
			6 -> uploadAcceptPeopleSignImage(offlineUpdateTaskBean)
			7 -> uploadServicePeopleSignImage(offlineUpdateTaskBean)
			8 -> taskFinish(offlineUpdateTaskBean)
		}
	}

	private fun uploadTask(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		val updateTaskRequest = UpdateTaskRequest(type = offlineUpdateTaskBean.type,
			taskId = offlineUpdateTaskBean.taskId,
			userId = offlineUpdateTaskBean.userId,
			vehicleId = offlineUpdateTaskBean.vehicleId,
			currentState = offlineUpdateTaskBean.currentState,
			operateTime = offlineUpdateTaskBean.operateTime,
			lat = offlineUpdateTaskBean.updateTaskLat,
			lng = offlineUpdateTaskBean.updateTaskLng,
			address = offlineUpdateTaskBean.updateTaskAddress,
			offlineMode = offlineUpdateTaskBean.offlineMode,
			flowType = offlineUpdateTaskBean.flowType,
			success = offlineUpdateTaskBean.success,
			templatePhotoInfoList = offlineUpdateTaskBean.templatePhotoInfoList)

		RetrofitHelper.getDefaultService().updateTask(updateTaskRequest)
			.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
			.subscribe(object : BaseObserver<UpdateTaskBean>() {
				override fun doSuccess(it : UpdateTaskBean?) {
					RoomHelper.db?.offlineTaskDao()
						?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
					isUploading = false
					offlineListener?.uploadSuccess()
					LogUtil.print("离线任务", "success=$it  request=${updateTaskRequest.toJson()}")
				}

				override fun doFailure(code : Int, msg : String?) {
					isUploading = false
					offlineListener?.uploadFailure(msg)
					LogUtil.print("离线任务",
						"uploadTask failed==${offlineUpdateTaskBean.toJson()}")
				}
			})
	}

	private fun uploadOrderImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		var file = File(offlineUpdateTaskBean.photoLocalWaterMarkerPath ?: "")
		if (! file.exists()) {
			offlineListener?.uploadFailure("图片未找到！")
			LogUtil.print("离线任务 uploadOrderImage",
				"uploadTask failed==${offlineUpdateTaskBean.toJson()}")
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			isUploading = false
			return
		}

		if (offlineUpdateTaskBean.imageAddress.isNullOrBlank() && (offlineUpdateTaskBean.imageLat != null && offlineUpdateTaskBean.imageLat != 0f && offlineUpdateTaskBean.imageLng != null && offlineUpdateTaskBean.imageLng != 0f)) {
			geoCoder(offlineUpdateTaskBean.imageLat.toDouble(),
				offlineUpdateTaskBean.imageLng.toDouble(),
				success = { it ->
					val photoMarkerInfo = PhotoMarkerInfo(offlineUpdateTaskBean.needWater,
						needShowPhoneBrand = offlineUpdateTaskBean.needPhoneBrand,
						path = offlineUpdateTaskBean.photoLocalWaterMarkerPath,
						from = "（离线）",
						lat = offlineUpdateTaskBean.imageLat.toDouble(),
						lng = offlineUpdateTaskBean.imageLng.toDouble(),
						address = it,
						time = offlineUpdateTaskBean.time,
						driverName = GlobalData.driverInfoBean?.userName,
						taskCode = offlineUpdateTaskBean.taskCode)
					val offlineTemp = offlineUpdateTaskBean.copy(imageAddress = it)
					file = File(PhotoMarkerManager.addPhotoMarker(ActivityUtils.getTopActivity(),
						photoMarkerInfo))
					CommonMethod.uploadImage(file = file, success = {
						val item = RoomHelper.db?.offlineTaskDao()
							?.getRecentOfflineTask(offlineTemp.taskId ?: 0)?.get(0)
						if (item == null) {
							offlineListener?.uploadFailure(it)
							isUploading = false
							return@uploadImage
						}
						LogUtil.print("离线任务 getRecentOfflineTask", "success=${item.toJson()}")
						val list = item.templatePhotoInfoList?.toMutableList()
						val jsonObject = JSONObject()
						jsonObject["realTakePhotoTime"] = offlineTemp.realTakePhotoTime ?: ""
						jsonObject["photoSource"] = offlineTemp.photoSource
						jsonObject["path"] = it
						jsonObject["time"] = offlineTemp.time
						jsonObject["lat"] = offlineTemp.imageLat
						jsonObject["lng"] = offlineTemp.imageLng
						jsonObject["address"] = offlineTemp.imageAddress
						list?.set(offlineTemp.imageIndex ?: 0, jsonObject.toJSONString())
						val temp = item.copy(templatePhotoInfoList = list?.toList())
						RoomHelper.db?.offlineTaskDao()?.update(temp)
						RoomHelper.db?.offlineTaskDao()
							?.deleteOfflineTaskFromId(offlineTemp.primaryId ?: 0)
						isUploading = false
						offlineListener?.uploadSuccess()
						LogUtil.print("离线任务 逆地理 uploadOrderImage",
							"success=$it  request=${offlineUpdateTaskBean.toJson()}")
					}, failed = {
						RoomHelper.db?.offlineTaskDao()?.update(offlineTemp)
						offlineListener?.uploadFailure(it)
						isUploading = false
					})
				},
				failed = {
					offlineListener?.uploadFailure(it)
					isUploading = false
				})
		} else {
			CommonMethod.uploadImage(file = file, success = {
				val item = RoomHelper.db?.offlineTaskDao()
					?.getRecentOfflineTask(offlineUpdateTaskBean.taskId ?: 0)?.get(0)
				if (item == null) {
					offlineListener?.uploadFailure(it)
					isUploading = false
					return@uploadImage
				}
				LogUtil.print("离线任务 getRecentOfflineTask", "success=${item.toJson()}")
				val list = item.templatePhotoInfoList?.toMutableList()
				val jsonObject = JSONObject()
				jsonObject["realTakePhotoTime"] = offlineUpdateTaskBean.realTakePhotoTime ?: ""
				jsonObject["photoSource"] = offlineUpdateTaskBean.photoSource
				jsonObject["path"] = it
				jsonObject["time"] = offlineUpdateTaskBean.time
				jsonObject["lat"] = offlineUpdateTaskBean.imageLat
				jsonObject["lng"] = offlineUpdateTaskBean.imageLng
				jsonObject["address"] = offlineUpdateTaskBean.imageAddress
				list?.set(offlineUpdateTaskBean.imageIndex ?: 0, jsonObject.toJSONString())
				val temp = item.copy(templatePhotoInfoList = list?.toList())

				RoomHelper.db?.offlineTaskDao()?.update(temp)
				RoomHelper.db?.offlineTaskDao()
					?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
				isUploading = false
				offlineListener?.uploadSuccess()
				LogUtil.print("离线任务 uploadOrderImage",
					"success=$it  request=${offlineUpdateTaskBean.toJson()}")
			}, failed = {
				offlineListener?.uploadFailure(it)
				isUploading = false
			})
		}
	}

	private fun uploadEleDamageImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		val file = File(offlineUpdateTaskBean.imageLocalPath ?: "")
		if (! file.exists()) {
			offlineListener?.uploadFailure("图片未找到！")
			LogUtil.print("离线任务 uploadEleDamageImage",
				"failed==${offlineUpdateTaskBean.toJson()}")
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			isUploading = false
			return
		}
		CommonMethod.uploadImage(file = file, success = {
			val item = RoomHelper.db?.offlineTaskDao()
				?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0)
			if (item == null) {
				offlineListener?.uploadFailure(it)
				isUploading = false
				return@uploadImage
			}
			LogUtil.print("离线任务 getRecentOfflineEle", "success=${item.toJson()}")
			val list = item.damageFileList?.toMutableList()
			list?.set(offlineUpdateTaskBean.imageIndex ?: 0, it)
			val temp = item.copy(templatePhotoInfoList = list?.toList())

			RoomHelper.db?.offlineTaskDao()?.update(temp)
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			isUploading = false
			offlineListener?.uploadSuccess()
			LogUtil.print("离线任务 uploadEleDamageImage",
				"success=$it  request=${offlineUpdateTaskBean.toJson()}")
		}, failed = {
			offlineListener?.uploadFailure(it)
			isUploading = false
		})
	}

	private fun uploadEleWorkOrder(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		val saveEleOrderRequest = SaveEleOrderRequest(state = offlineUpdateTaskBean.eleState,
			userOrderId = offlineUpdateTaskBean.userOrderId,
			taskOrderId = offlineUpdateTaskBean.taskId,
			damageFileList = offlineUpdateTaskBean.damageFileList,
			hasDamage = offlineUpdateTaskBean.hasDamage,
			hasSuccess = offlineUpdateTaskBean.hasSuccess,
			customerSignPath = offlineUpdateTaskBean.customerSignPath,
			recipientSignPath = offlineUpdateTaskBean.recipientSignPath,
			waitstaffSignPath = offlineUpdateTaskBean.waitstaffSignPath,
			offlineMode = 1,
			userOrderCode = offlineUpdateTaskBean.userOrderCode,
			lat = offlineUpdateTaskBean.eleLat,
			lng = offlineUpdateTaskBean.eleLng,
			tyreNumber = offlineUpdateTaskBean.tyreNumber,
			isFinish = offlineUpdateTaskBean.isFinish)
		LogUtil.print("离线数据 eleSign_check request", saveEleOrderRequest.toJson() ?: "")
		RetrofitHelper.getDefaultService().saveElectronOrder(saveEleOrderRequest)
			.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
			.subscribe(object : BaseObserver<String>() {
				override fun doSuccess(it : String?) {
					RoomHelper.db?.offlineTaskDao()
						?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
					isUploading = false
					offlineListener?.uploadSuccess()
					LogUtil.print("离线任务 uploadEleWorkOrder",
						"success=$it  request=${offlineUpdateTaskBean.toJson()}")
				}

				override fun doFailure(code : Int, msg : String?) {
					offlineListener?.uploadFailure(msg)
					isUploading = false
				}
			})
	}

	private fun uploadCustomerSignImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		val file = File(offlineUpdateTaskBean.imageLocalPath ?: "")
		if (! file.exists()) {
			offlineListener?.uploadFailure("图片未找到！")
			LogUtil.print("离线任务 uploadCustomerSignImage",
				"failed==${offlineUpdateTaskBean.toJson()}")
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			isUploading = false
			return
		}
		CommonMethod.uploadImage(file = file, success = { it ->
			val item = RoomHelper.db?.offlineTaskDao()
				?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0)
			if (item == null) {
				offlineListener?.uploadFailure(it)
				isUploading = false
				return@uploadImage
			}
			LogUtil.print("离线任务 uploadCustomerSignImage getRecentOfflineEle",
				"success=${item.toJson()}")
			RoomHelper.db?.offlineTaskDao()?.update(item.copy(customerSignPath = it))
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(offlineUpdateTaskBean.taskId ?: 0)
				?.copy(serverCustomSignPath = it)?.let {
					RoomHelper.db?.eleWorkOrderDao()?.update(it)
				}
			isUploading = false
			offlineListener?.uploadSuccess()
			LogUtil.print("离线任务 uploadCustomerSignImage",
				"success=$it  request=${offlineUpdateTaskBean.toJson()}")
		}, failed = {
			offlineListener?.uploadFailure(it)
			isUploading = false
		})
	}

	private fun uploadAcceptPeopleSignImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		val file = File(offlineUpdateTaskBean.imageLocalPath ?: "")
		if (! file.exists()) {
			offlineListener?.uploadFailure("图片未找到！")
			LogUtil.print("离线任务 uploadCustomerSignImage",
				"failed==${offlineUpdateTaskBean.toJson()}")
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			isUploading = false
			return
		}
		CommonMethod.uploadImage(file = file, success = { it ->
			val item = RoomHelper.db?.offlineTaskDao()
				?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0)
			if (item == null) {
				offlineListener?.uploadFailure(it)
				isUploading = false
				return@uploadImage
			}
			LogUtil.print("离线任务 uploadAcceptPeopleSignImage getRecentOfflineEle",
				"success=${item.toJson()}")
			RoomHelper.db?.offlineTaskDao()?.update(item.copy(recipientSignPath = it))
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(offlineUpdateTaskBean.taskId ?: 0)
				?.copy(serverAcceptCarSignPath = it)?.let {
					RoomHelper.db?.eleWorkOrderDao()?.update(it)
				}
			isUploading = false
			offlineListener?.uploadSuccess()
			LogUtil.print("离线任务 uploadAcceptPeopleSignImage",
				"success=$it  request=${offlineUpdateTaskBean.toJson()}")
		}, failed = {
			offlineListener?.uploadFailure(it)
			isUploading = false
		})
	}

	private fun uploadServicePeopleSignImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		val file = File(offlineUpdateTaskBean.imageLocalPath ?: "")
		if (! file.exists()) {
			offlineListener?.uploadFailure("图片未找到！")
			LogUtil.print("离线任务 uploadCustomerSignImage",
				"failed==${offlineUpdateTaskBean.toJson()}")
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			isUploading = false
			return
		}
		CommonMethod.uploadImage(file = file, success = { it ->
			val item = RoomHelper.db?.offlineTaskDao()
				?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0)
			if (item == null) {
				offlineListener?.uploadFailure(it)
				isUploading = false
				return@uploadImage
			}
			LogUtil.print("离线任务 uploadCustomerSignImage getRecentOfflineEle",
				"success=${item.toJson()}")
			RoomHelper.db?.offlineTaskDao()?.update(item.copy(waitstaffSignPath = it))
			RoomHelper.db?.offlineTaskDao()
				?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
			RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(offlineUpdateTaskBean.taskId ?: 0)
				?.copy(serverServicePeopleSignPath = it)?.let {
					RoomHelper.db?.eleWorkOrderDao()?.update(it)
				}

			isUploading = false
			offlineListener?.uploadSuccess()
			LogUtil.print("离线任务 uploadCustomerSignImage",
				"success=$it  request=${offlineUpdateTaskBean.toJson()}")
		}, failed = {
			offlineListener?.uploadFailure(it)
			isUploading = false
		})
	}

	private fun taskFinish(offlineUpdateTaskBean : OfflineUpdateTaskBean) {
		isUploading = true
		val taskFinishRequest = TaskFinishRequest(
			operateTime = offlineUpdateTaskBean.operateTime?.toLong(),
			lat = offlineUpdateTaskBean.updateTaskLat,
			userOrderId = offlineUpdateTaskBean.userOrderId,
			lng = offlineUpdateTaskBean.updateTaskLng,
		)
		RetrofitHelper.getDefaultService().taskFinish(taskFinishRequest)
			.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
			.subscribe(object : BaseObserver<TaskFinishResponse>() {
				override fun doSuccess(it : TaskFinishResponse?) {
					RoomHelper.db?.offlineTaskDao()
						?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0)
					isUploading = false
					offlineListener?.uploadSuccess()
					LogUtil.print("离线任务", "success=$it  request=${taskFinishRequest.toJson()}")
				}

				override fun doFailure(code : Int, msg : String?) {
					isUploading = false
					offlineListener?.uploadFailure(msg)
					LogUtil.print("离线任务",
						"uploadTask failed==${offlineUpdateTaskBean.toJson()}")
				}
			})
	}
}

//打开系统悬浮窗权限
private fun openSystemAlertPermissionDialog() {
	val context = ActivityUtils.getTopActivity()
	val alertdialog = AlertDialog.Builder(ActivityUtils.getTopActivity()).setTitle("提示")
		.setMessage("当前应用缺少【悬浮窗】必要权限。\n\n请点击\"设置\"-\"权限\"-打开所需权限。")
		.setCancelable(false).setPositiveButton("设置") { _, _ ->
			val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
				"package:${context.packageName}".toUri())
			intent.data = ("package:" + ActivityUtils.getTopActivity().packageName).toUri()
			ActivityUtils.getTopActivity().startActivity(intent)
		}
	alertdialog.show()
}

//逆地址编码
private fun geoCoder(lat : Double,
	lng : Double,
	success : (String) -> Unit,
	failed : (String) -> Unit = {}) {
	val geocoderSearch = GeocodeSearch(ActivityUtils.getTopActivity().application)
	val query = RegeocodeQuery(LatLonPoint(lat, lng), 200f, GeocodeSearch.AMAP)
	geocoderSearch.getFromLocationAsyn(query)
	geocoderSearch.setOnGeocodeSearchListener(object : OnGeocodeSearchListener {
		override fun onRegeocodeSearched(regeocodeResult : RegeocodeResult, i : Int) {
			if (i == 1000) {
				success(regeocodeResult.regeocodeAddress.formatAddress)
				LogUtil.print("离线任务 singleLocation 逆地理编码",
					regeocodeResult.regeocodeAddress.formatAddress)
			} else {
				failed("地址获取失败")
				LogUtil.print("singleLocation 逆地理失败 ", regeocodeResult.toString())
			}
		}

		override fun onGeocodeSearched(geocodeResult : GeocodeResult, i : Int) {}
	})
}