package com.pixelized.desktop.lwa.ui.screen.admin.alteration.edit

import com.pixelized.desktop.lwa.ui.composable.textfield.createLwaTextField
import com.pixelized.desktop.lwa.ui.composable.textfield.createLwaTextFieldFlow
import com.pixelized.desktop.lwa.ui.screen.admin.common.tag.GMTagFactory
import com.pixelized.shared.lwa.model.alteration.Alteration
import com.pixelized.shared.lwa.model.tag.Tag
import com.pixelized.shared.lwa.parser.expression.ExpressionParser
import kotlinx.coroutines.flow.MutableStateFlow
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.game_master__alteration__edit_description
import lwacharactersheet.composeapp.generated.resources.game_master__alteration__edit_field_expression
import lwacharactersheet.composeapp.generated.resources.game_master__alteration__edit_field_id
import lwacharactersheet.composeapp.generated.resources.game_master__alteration__edit_icon
import lwacharactersheet.composeapp.generated.resources.game_master__alteration__edit_id
import lwacharactersheet.composeapp.generated.resources.game_master__alteration__edit_label
import org.jetbrains.compose.resources.getString
import java.util.UUID

class GMAlterationEditFactory(
    private val expressionParser: ExpressionParser,
    private val tagFactory: GMTagFactory,
) {
    suspend fun createForm(
        alteration: Alteration?,
        tags: Collection<Tag>,
    ): GMAlterationEditViewModel.GMAlterationEditForm {
        val idFlow = createLwaTextFieldFlow(
            label = getString(Res.string.game_master__alteration__edit_id),
            value = alteration?.id ?: "",
        )
        val labelFlow = createLwaTextFieldFlow(
            label = getString(Res.string.game_master__alteration__edit_label),
            value = alteration?.metadata?.name ?: "",
        )
        val descriptionFlow = createLwaTextFieldFlow(
            label = getString(Res.string.game_master__alteration__edit_description),
            value = alteration?.metadata?.description ?: "",
        )
        val iconFlow = createLwaTextFieldFlow(
            label = getString(Res.string.game_master__alteration__edit_icon),
            value = alteration?.metadata?.icon ?: "",
        )
        val tagFlow = MutableStateFlow(
            tagFactory.convertToGMTagItemUio(
                tags = tags,
                selectedTagIds = alteration?.tags ?: emptyList(),
            )
        )
        val fieldsFlow = MutableStateFlow(alteration?.fields?.map { createField(it) }
            ?: listOf(createField(null)))
        return GMAlterationEditViewModel.GMAlterationEditForm(
            idFlow = idFlow,
            labelFlow = labelFlow,
            descriptionFlow = descriptionFlow,
            iconFlow = iconFlow,
            tagFlow = tagFlow,
            fieldsFlow = fieldsFlow,
        )
    }

    suspend fun createForm(
        originId: String?,
        form: GMAlterationEditViewModel.GMAlterationEditForm,
    ): GMAlterationEditPageUio {
        return GMAlterationEditPageUio(
            id = form.idFlow.createLwaTextField(enable = originId == null),
            label = form.labelFlow.createLwaTextField(),
            description = form.descriptionFlow.createLwaTextField(),
            icon = form.iconFlow.createLwaTextField(),
            tags = form.tagFlow,
            fields = form.fieldsFlow,
        )
    }

    suspend fun createField(
        alteration: Alteration.Field?,
    ): GMAlterationEditPageUio.SkillUio {
        val idFlow = createLwaTextFieldFlow(
            label = getString(Res.string.game_master__alteration__edit_field_id),
            value = alteration?.fieldId ?: "",
        )
        val expressionFlow = createLwaTextFieldFlow(
            label = getString(Res.string.game_master__alteration__edit_field_expression),
            value = alteration?.expression?.toString() ?: "",
        )
        return GMAlterationEditPageUio.SkillUio(
            key = "${UUID.randomUUID()}-${System.currentTimeMillis()}",
            id = idFlow.createLwaTextField(),
            expression = expressionFlow.createLwaTextField()
        )
    }

    fun createAlteration(
        form: GMAlterationEditViewModel.GMAlterationEditForm?,
    ): Alteration? {
        if (form == null) return null

        return Alteration(
            id = form.idFlow.valueFlow.value,
            metadata = Alteration.MetaData(
                name = form.labelFlow.valueFlow.value,
                description = form.descriptionFlow.valueFlow.value,
                icon = form.iconFlow.valueFlow.value.takeIf { it.isNotBlank() },
            ),
            tags = form.tagFlow.value
                .filter { it.highlight }
                .map { it.id },
            fields = form.fieldsFlow.value.mapNotNull { field ->
                expressionParser.parse(input = field.expression.valueFlow.value)?.let {
                    Alteration.Field(
                        fieldId = field.id.valueFlow.value,
                        expression = it
                    )
                }
            }
        )
    }
}