/*
 * Book's Story — free and open-source Material You eBook reader.
 * Copyright (C) 2024-2026 Acclorite
 * SPDX-License-Identifier: GPL-3.0-only
 */

package org.dueattendant149.bookshelf.presentation.settings

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.dueattendant149.bookshelf.data.settings.ServerSettings
import org.dueattendant149.bookshelf.domain.model.remote.RemoteLibrary
import org.dueattendant149.bookshelf.domain.use_case.remote.CheckHealthUseCase
import org.dueattendant149.bookshelf.domain.use_case.remote.FetchLibrariesUseCase
import org.dueattendant149.bookshelf.domain.util.deriveAbsUrl
import javax.inject.Inject

data class BookshelfSettingsState(
    val bookshelfUrl: String = "",
    val absUrl: String = "",
    val absToken: String = "",
    val libraries: List<RemoteLibrary> = emptyList(),
    val isLoading: Boolean = false,
    val isCheckingConnection: Boolean = false,
    val connectionError: String? = null,
    val connectionSuccess: Boolean = false,
    val error: String? = null,
    val librariesSuccess: Boolean = false,
)

@HiltViewModel
class BookshelfSettingsModel
    @Inject
    constructor(
        private val serverSettings: ServerSettings,
        private val fetchLibrariesUseCase: FetchLibrariesUseCase,
        private val checkHealthUseCase: CheckHealthUseCase,
    ) : ViewModel() {
        private val _state = MutableStateFlow(BookshelfSettingsState())
        val state = _state.asStateFlow()

        init {
            load()
        }

        fun load() {
            viewModelScope.launch {
                _state.update {
                    it.copy(
                        bookshelfUrl = serverSettings.getBookshelfUrl() ?: "",
                        absUrl = serverSettings.getAbsUrl() ?: "",
                        absToken = serverSettings.getAbsToken() ?: "",
                    )
                }
            }
        }

        fun updateBookshelfUrl(value: String) = _state.update {
            it.copy(
                bookshelfUrl = value,
                librariesSuccess = false,
                connectionSuccess = false,
                connectionError = null,
                error = null,
            )
        }

        fun updateAbsUrl(value: String) = _state.update {
            it.copy(
                absUrl = value,
                librariesSuccess = false,
                connectionSuccess = false,
                connectionError = null,
                error = null,
            )
        }

        fun updateAbsToken(value: String) = _state.update {
            it.copy(
                absToken = value,
                librariesSuccess = false,
                connectionSuccess = false,
                connectionError = null,
                error = null,
            )
        }

        fun deriveAbsUrlFromBookshelf() {
            viewModelScope.launch {
                val derived = _state.value.bookshelfUrl.deriveAbsUrl()
                if (derived != null) {
                    _state.update {
                        it.copy(
                            absUrl = derived,
                            librariesSuccess = false,
                            error = null,
                        )
                    }
                }
            }
        }

        fun save() {
            viewModelScope.launch {
                val current = _state.value
                serverSettings.setBookshelfUrl(current.bookshelfUrl)
                serverSettings.setAbsUrl(current.absUrl)
                serverSettings.setAbsToken(current.absToken)
            }
        }

        fun checkConnection() {
            viewModelScope.launch {
                _state.update {
                    it.copy(
                        isCheckingConnection = true,
                        connectionError = null,
                        connectionSuccess = false,
                    )
                }
                save()

                val url = _state.value.bookshelfUrl
                val result = checkHealthUseCase(url)
                _state.update {
                    it.copy(
                        isCheckingConnection = false,
                        connectionSuccess = result.isSuccess,
                        connectionError = result.exceptionOrNull()?.message,
                    )
                }
            }
        }

        fun testLibraries() {
            viewModelScope.launch {
                _state.update {
                    it.copy(
                        isLoading = true,
                        error = null,
                        librariesSuccess = false,
                    )
                }
                save()

                val missingError = serverSettings.getMissingCredentialsError()
                if (missingError != null) {
                    _state.update {
                        it.copy(
                            isLoading = false,
                            libraries = emptyList(),
                            error = missingError,
                        )
                    }
                    return@launch
                }

                val result = fetchLibrariesUseCase()
                val libraries = result.getOrDefault(emptyList())
                _state.update {
                    it.copy(
                        isLoading = false,
                        libraries = libraries,
                        error = result.exceptionOrNull()?.message,
                        librariesSuccess = result.isSuccess && libraries.isNotEmpty(),
                    )
                }
            }
        }
    }
