package com.pixelized.desktop.lwa.ui.composable.character.characteristic

import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogUio.Characteristic
import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update

class CharacterSheetCharacteristicDialogViewModel(
    private val characterSheetRepository: CharacterSheetRepository,
    private val alterationRepository: AlterationRepository,
    private val alteredCharacterSheetFactory: AlteredCharacterSheetFactory,
    private val factory: CharacterSheetCharacteristicDialogFactory,
    private val network: NetworkRepository,
) : ViewModel() {

    private val signFlow = MutableStateFlow(false)

    private val _statChangeDialog = mutableStateOf<CharacterSheetCharacteristicDialogUio?>(null)
    val statChangeDialog: State<CharacterSheetCharacteristicDialogUio?> get() = _statChangeDialog

    fun hideSubCharacteristicDialog() {
        _statChangeDialog.value = null
    }

    fun swapCharacteristicSign() {
        signFlow.update { it.not() }
    }

    suspend fun showSubCharacteristicDialog(
        characterSheetId: String?,
        characteristic: Characteristic,
    ) {
        signFlow.update { false }
        _statChangeDialog.value = factory.convertToDialogUio(
            scope = viewModelScope,
            characterSheetId = characterSheetId,
            characteristic = characteristic,
            signFlow = signFlow,
        )
    }

    suspend fun changeSubCharacteristic(
        characterSheetId: String?,
        characteristic: Characteristic,
        useArmor: Boolean,
        value: Int,
    ) {
        if (characterSheetId == null) return

        // fetch the linked character sheet, if null stop exit this function.
        val characterSheet = characterSheetRepository.characterDetail(
            characterSheetId = characterSheetId,
        )

        if (characterSheet == null) return

        val sign = if (signFlow.value) 1 else -1

        val message = when (characteristic) {
            Characteristic.Damage -> {
                val armor = if (useArmor && signFlow.value.not()) {
                    val alterations = alterationRepository.activeFieldAlterations(
                        characterSheetId = characterSheetId,
                    )
                    val alteredSheet = alteredCharacterSheetFactory.sheet(
                        characterSheet = characterSheet,
                        alterations = alterations,
                    )
                    alteredSheet.armor
                } else {
                    null
                }

                CharacterSheetEvent.UpdateDamage(
                    timestamp = System.currentTimeMillis(),
                    characterSheetId = characterSheetId,
                    oldValue = characterSheet.damage,
                    damage = characterSheet.damage - value * sign - (armor ?: 0),
                    armor = armor,
                )
            }

            Characteristic.Fatigue -> CharacterSheetEvent.UpdateFatigue(
                timestamp = System.currentTimeMillis(),
                characterSheetId = characterSheetId,
                oldValue = characterSheet.fatigue,
                fatigue = characterSheet.fatigue - value * sign,
            )
        }

        // share the data through the websocket.
        network.share(
            message = message,
        )
    }
}