package kr.co.vividnext.sodalive.live.room.update

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import com.orhanobut.logger.Logger
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.base.BaseViewModel
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.extensions.convertDateFormat
import kr.co.vividnext.sodalive.live.LiveRepository
import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailResponse
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import java.util.Locale
import java.util.TimeZone

class LiveRoomEditViewModel(
    private val repository: LiveRepository
) : BaseViewModel() {

    private val _reservationDateLiveData = MutableLiveData("날짜를 선택해주세요")
    val reservationDateLiveData: LiveData<String>
        get() = _reservationDateLiveData

    private val _reservationTimeLiveData = MutableLiveData("시간을 설정해주세요")
    val reservationTimeLiveData: LiveData<String>
        get() = _reservationTimeLiveData

    private val _toastLiveData = MutableLiveData<String?>()
    val toastLiveData: LiveData<String?>
        get() = _toastLiveData

    private var _isLoading = MutableLiveData(false)
    val isLoading: LiveData<Boolean>
        get() = _isLoading

    private lateinit var roomDetail: GetRoomDetailResponse

    var title = ""
    var content = ""
    var numberOfPeople = 0
    var beginDate = ""
    var beginTime = ""
    var beginDateTimeStr = ""

    fun setReservationDate(dateString: String) {
        _reservationDateLiveData.postValue(dateString)
    }

    fun setReservationTime(timeString: String) {
        _reservationTimeLiveData.postValue(timeString)
    }

    fun updateLiveRoom(onSuccess: () -> Unit) {
        if (!_isLoading.value!! && validateData()) {
            _isLoading.value = true
            val request = EditLiveRoomInfoRequest(
                title = if (title != roomDetail.title) {
                    title
                } else {
                    null
                },
                notice = if (content != roomDetail.notice) {
                    content
                } else {
                    null
                },
                numberOfPeople = if (numberOfPeople != roomDetail.numberOfParticipantsTotal) {
                    numberOfPeople
                } else {
                    null
                },
                beginDateTimeString = if (beginDateTimeStr != "$beginDate $beginTime") {
                    "$beginDate $beginTime"
                } else {
                    null
                },
                timezone = TimeZone.getDefault().id
            )

            if (
                request.title == null &&
                request.notice == null &&
                request.numberOfPeople == null &&
                request.beginDateTimeString == null
            ) {
                _toastLiveData.value = "변경사항이 없습니다."
                _isLoading.value = false
                return
            }

            val requestJson = Gson().toJson(request)

            compositeDisposable.add(
                repository.editLiveRoomInfo(
                    roomId = roomDetail.roomId,
                    request = requestJson.toRequestBody("text/plain".toMediaType()),
                    token = "Bearer ${SharedPreferenceManager.token}"
                )
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(
                        {
                            if (it.success && it.data != null) {
                                _toastLiveData.value = "라이브 정보가 수정 되었습니다."
                                onSuccess()
                            } else {
                                if (it.message != null) {
                                    _toastLiveData.postValue(it.message)
                                } else {
                                    _toastLiveData.postValue(
                                        "라이브 정보를 수정 하지 못했습니다.\n다시 시도해 주세요."
                                    )
                                }
                            }
                            _isLoading.postValue(false)
                        },
                        {
                            _isLoading.postValue(false)
                            it.message?.let { message -> Logger.e(message) }
                            _toastLiveData.postValue(
                                "라이브 정보를 수정 하지 못했습니다.\n다시 시도해 주세요."
                            )
                        }
                    )
            )
        }
    }

    fun setRoomDetail(roomDetail: GetRoomDetailResponse) {
        this.roomDetail = roomDetail
        val date = roomDetail.beginDateTime.convertDateFormat(
            from = "yyyy.MM.dd EEE hh:mm a",
            to = "yyyy.MM.dd",
            inputLocale = Locale.ENGLISH
        )

        val time = roomDetail.beginDateTime.convertDateFormat(
            from = "yyyy.MM.dd EEE hh:mm a",
            to = "a hh:mm",
            inputLocale = Locale.ENGLISH
        )

        _reservationDateLiveData.value = date
        _reservationTimeLiveData.value = time

        beginDate = date.convertDateFormat(
            from = "yyyy.MM.dd",
            to = "yyyy-MM-dd",
        )

        beginTime = time.convertDateFormat(
            from = "a hh:mm",
            to = "HH:mm",
        )

        beginDateTimeStr = "$beginDate $beginTime"
    }

    private fun validateData(): Boolean {
        if (title.isBlank()) {
            _toastLiveData.postValue("제목을 입력해주세요.")
            return false
        }

        if (content.isBlank() || content.length < 5) {
            _toastLiveData.postValue("내용을 5자 이상 입력해주세요.")
            return false
        }

        if (numberOfPeople < 3 || numberOfPeople > 999) {
            _toastLiveData.postValue("인원을 3~999명 사이로 입력해주세요.")
            return false
        }

        return true
    }
}
