package kr.co.vividnext.sodalive.explorer.profile

import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.firebase.dynamiclinks.ShortDynamicLink
import com.google.firebase.dynamiclinks.ktx.androidParameters
import com.google.firebase.dynamiclinks.ktx.dynamicLinks
import com.google.firebase.dynamiclinks.ktx.iosParameters
import com.google.firebase.dynamiclinks.ktx.shortLinkAsync
import com.google.firebase.ktx.Firebase
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.explorer.ExplorerRepository
import kr.co.vividnext.sodalive.explorer.profile.cheers.PutModifyCheersRequest
import kr.co.vividnext.sodalive.report.ReportRepository
import kr.co.vividnext.sodalive.report.ReportRequest
import kr.co.vividnext.sodalive.report.ReportType
import kr.co.vividnext.sodalive.user.UserRepository

class UserProfileViewModel(
    private val repository: ExplorerRepository,
    private val reportRepository: ReportRepository,
    private val userRepository: UserRepository
) : BaseViewModel() {
    private val _toastLiveData = MutableLiveData<String?>()
    val toastLiveData: LiveData<String?>
        get() = _toastLiveData

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

    private var _creatorProfileLiveData = MutableLiveData<GetCreatorProfileResponse>()
    val creatorProfileLiveData: LiveData<GetCreatorProfileResponse>
        get() = _creatorProfileLiveData

    private var creatorNickname = ""

    fun cheersReport(cheersId: Long, reason: String) {
        _isLoading.value = true

        val request = ReportRequest(ReportType.CHEERS, reason, cheersId = cheersId)
        compositeDisposable.add(
            reportRepository.report(
                request = request,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        if (it.message != null) {
                            _toastLiveData.postValue(it.message)
                        } else {
                            _toastLiveData.postValue(
                                "신고가 접수되었습니다."
                            )
                        }

                        _isLoading.value = false
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("신고가 접수되었습니다.")
                    }
                )
        )
    }

    fun report(type: ReportType, userId: Long, reason: String = "프로필 신고") {
        _isLoading.value = true

        val request = ReportRequest(type, reason, reportedMemberId = userId)
        compositeDisposable.add(
            reportRepository.report(
                request = request,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        if (it.message != null) {
                            _toastLiveData.postValue(it.message)
                        } else {
                            _toastLiveData.postValue(
                                "신고가 접수되었습니다."
                            )
                        }

                        _isLoading.value = false
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("신고가 접수되었습니다.")
                    }
                )
        )
    }

    fun getCreatorProfile(userId: Long, onFailure: (() -> Unit)? = null) {
        _isLoading.value = true
        compositeDisposable.add(
            repository.getCreatorProfile(
                id = userId,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        if (it.success && it.data != null) {
                            val data = it.data
                            _creatorProfileLiveData.postValue(data!!)
                        } else {
                            if (it.message != null) {
                                _toastLiveData.postValue(it.message)
                            } else {
                                _toastLiveData.postValue(
                                    "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                                )
                            }

                            if (onFailure != null) {
                                onFailure()
                            }
                        }

                        _isLoading.value = false
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                        if (onFailure != null) {
                            onFailure()
                        }
                    }
                )
        )
    }

    fun follow(creatorId: Long, follow: Boolean = true, notify: Boolean = true) {
        _isLoading.value = true
        compositeDisposable.add(
            userRepository.creatorFollow(
                creatorId,
                follow = follow,
                notify = notify,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        if (it.success && it.data != null) {
                            getCreatorProfile(creatorId)
                        } else {
                            if (it.message != null) {
                                _toastLiveData.postValue(it.message)
                            } else {
                                _toastLiveData.postValue(
                                    "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                                )
                            }
                        }
                        _isLoading.value = false
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                    }
                )
        )
    }

    fun unFollow(creatorId: Long) {
        _isLoading.value = true
        compositeDisposable.add(
            userRepository.creatorUnFollow(
                creatorId,
                "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        if (it.success && it.data != null) {
                            getCreatorProfile(creatorId)
                        } else {
                            if (it.message != null) {
                                _toastLiveData.postValue(it.message)
                            } else {
                                _toastLiveData.postValue(
                                    "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                                )
                            }
                        }
                        _isLoading.value = false
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                    }
                )
        )
    }

    fun writeCheers(parentCheersId: Long? = null, creatorId: Long, cheersContent: String) {
        if (cheersContent.isBlank()) {
            _toastLiveData.postValue("내용을 입력하세요")
            return
        }

        _isLoading.value = true

        compositeDisposable.add(
            repository.writeCheers(
                parentCheersId = parentCheersId,
                creatorId = creatorId,
                content = cheersContent,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        _isLoading.value = false

                        if (it.success) {
                            getCreatorProfile(creatorId)
                        } else {
                            val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                            _toastLiveData.postValue(message)
                        }
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                    }
                )
        )
    }

    fun modifyCheers(
        cheersId: Long,
        creatorId: Long,
        cheersContent: String? = null,
        isActive: Boolean? = null
    ) {
        if (cheersContent == null && isActive == null) {
            _toastLiveData.postValue("변경사항이 없습니다.")
            return
        }

        if (cheersContent != null && cheersContent.isBlank()) {
            _toastLiveData.postValue("내용을 입력하세요")
            return
        }

        _isLoading.value = true

        val request = PutModifyCheersRequest(cheersId = cheersId)

        if (cheersContent != null) {
            request.content = cheersContent
        }

        if (isActive != null) {
            request.isActive = isActive
        }

        compositeDisposable.add(
            repository.modifyCheers(
                request = request,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        _isLoading.value = false

                        if (it.success) {
                            getCreatorProfile(creatorId)
                        } else {
                            val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                            _toastLiveData.postValue(message)
                        }
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                    }
                )
        )
    }

    fun shareChannel(userId: Long, onSuccess: (String) -> Unit) {
        _isLoading.value = true
        Firebase.dynamicLinks.shortLinkAsync(ShortDynamicLink.Suffix.SHORT) {
            link = Uri.parse("https://sodalive.net/?channel_id=$userId")
            domainUriPrefix = "https://sodalive.page.link"
            androidParameters { }
            iosParameters("kr.co.vividnext.sodalive") {
                appStoreId = "6461721697"
            }
        }.addOnSuccessListener {
            val uri = it.shortLink
            if (uri != null) {
                onSuccess("보이스온 ${creatorNickname}님의 채널입니다.\n$uri")
            }
        }.addOnFailureListener {
            _toastLiveData.postValue("공유링크를 생성하지 못했습니다.\n다시 시도해 주세요.")
        }.addOnCompleteListener {
            _isLoading.value = false
        }
    }

    fun userBlock(userId: Long) {
        _isLoading.value = true
        compositeDisposable.add(
            userRepository.memberBlock(
                userId = userId,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        _isLoading.value = false

                        if (it.success) {
                            getCreatorProfile(userId)
                            _toastLiveData.postValue("차단하였습니다.")
                        } else {
                            val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                            _toastLiveData.postValue(message)
                        }
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                    }
                )
        )
    }

    fun userUnBlock(userId: Long) {
        _isLoading.value = true
        compositeDisposable.add(
            userRepository.memberUnBlock(
                userId = userId,
                token = "Bearer ${SharedPreferenceManager.token}"
            )
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    {
                        _isLoading.value = false

                        if (it.success) {
                            getCreatorProfile(userId)
                            _toastLiveData.postValue("차단이 해제 되었습니다.")
                        } else {
                            val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
                            _toastLiveData.postValue(message)
                        }
                    },
                    {
                        _isLoading.value = false
                        it.message?.let { message -> Logger.e(message) }
                        _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
                    }
                )
        )
    }
}
