package com.isidroid.c23.ui.screen.content

import android.net.Uri
import androidx.lifecycle.viewModelScope
import com.isidroid.c23.domain.use_case.ContentUseCase
import com.isidroid.c23.ext.isDebug
import com.isidroid.core.FlowResult
import com.isidroid.core.vm.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import java.util.UUID
import javax.inject.Inject

@HiltViewModel
class ContentViewModel @Inject constructor(
    private val useCase: ContentUseCase
) : BaseViewModel<ContentContract.Event, ContentContract.State, ContentContract.Effect>() {
    init {
        viewModelScope.launch { create() }
    }

    override val isDebug: Boolean = isDebug()
    override fun setInitialState(): ContentContract.State = ContentContract.State()
    override suspend fun handleEvents(event: ContentContract.Event) {
        when (event) {
            is ContentContract.Event.MultipleContents -> onContentSelected(event.uris)
            is ContentContract.Event.PickContent -> setState {
                copy(
                    galleryHash = if (event.photo) UUID.randomUUID().toString() else null,
                    documentHash = if (event.documents) UUID.randomUUID().toString() else null,
                    wordHash = if (event.word) UUID.randomUUID().toString() else null,
                )
            }

            is ContentContract.Event.OpenMap -> setEffect { ContentContract.Effect.Navigation.ToMap(event.lat, event.lng, event.spotCode) }
            ContentContract.Event.GoBack -> setEffect { ContentContract.Effect.Navigation.ToBack }
            ContentContract.Event.ToPrintJobList -> setEffect { ContentContract.Effect.Navigation.ToPrintJobList }
            ContentContract.Event.CheckNotificationPermission -> setState { copy(hasNotificationPermission = null) }
            ContentContract.Event.OpenDocumentTreeToCopyRenderedFiles -> setState { copy(documentTreeHash = UUID.randomUUID().toString()) }
            is ContentContract.Event.CopyRenderedFilesToPublicFolder -> copyRenderedFilesToPublicFolder(event.uri)
        }
    }

    private fun onContentSelected(uris: List<Uri>) {
        if (uris.isEmpty())
            return

        setState { copy(galleryHash = null, documentHash = null, wordHash = null) }
        setEffect { ContentContract.Effect.Navigation.ToRenderPreview(uris.joinToString()) }
    }

    private suspend fun create() {
        useCase.create().flowOn(Dispatchers.IO).collect {
            val (data, hasPermission) = it

            if (data == null)
                setEffect { ContentContract.Effect.Navigation.ToMap() }
            else
                setState { copy(richSpot = data, hasNotificationPermission = hasPermission) }
        }
    }

    private suspend fun copyRenderedFilesToPublicFolder(uri: Uri?) {
        setState { copy(documentTreeHash = null) }
        uri ?: return

        useCase.copyRenderedFilesToPublicFolder(uri)
            .flowOn(Dispatchers.IO)
            .collect { res ->
                when (res) {
                    FlowResult.Loading -> {}
                    is FlowResult.Success -> setEffect { ContentContract.Effect.RenderedFilesCopied(res.result) }
                }
            }
    }
}