package de.haushalt.app.ui.schema

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import de.haushalt.app.data.ApiClient
import de.haushalt.app.data.TaskSchema
import de.haushalt.app.data.TaskSchemaRequest
import de.haushalt.app.data.TaskSchemaStatus
import de.haushalt.app.data.TaskStatus
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonPrimitive

class SchemaEditViewModel : ViewModel() {
    var name by mutableStateOf("")
    var status by mutableStateOf(TaskSchemaStatus.active)
    var taskStatus by mutableStateOf(TaskStatus.active)
    var repeatType by mutableStateOf("none")
    var date by mutableStateOf("")
    var start by mutableStateOf("")
    var end by mutableStateOf("")
    var weekly by mutableStateOf(List(7) { false })
    var monthly by mutableStateOf(List(31) { false })
    var days by mutableStateOf(listOf<String>())
    var isLoading by mutableStateOf(false)
        private set
    var isSubmitting by mutableStateOf(false)
        private set
    var error by mutableStateOf<String?>(null)
        private set

    fun load(id: Int) {
        viewModelScope.launch {
            isLoading = true
            error = null
            try {
                val schema = ApiClient.schemaApi.get(id)
                applySchema(schema)
            } catch (e: Exception) {
                error = e.message
            } finally {
                isLoading = false
            }
        }
    }

    fun update(id: Int, onSuccess: () -> Unit) {
        viewModelScope.launch {
            isSubmitting = true
            error = null
            try {
                ApiClient.schemaApi.update(id, buildRequest())
                onSuccess()
            } catch (e: Exception) {
                error = e.message
            } finally {
                isSubmitting = false
            }
        }
    }

    private fun applySchema(schema: TaskSchema) {
        name = schema.name
        status = schema.status
        taskStatus = schema.taskStatus
        date = schema.date?.take(10) ?: ""
        start = schema.start?.take(10) ?: ""
        end = schema.end?.take(10) ?: ""

        when {
            schema.repeat == null -> {
                repeatType = "none"
                weekly = List(7) { false }
                monthly = List(31) { false }
                days = listOf()
            }
            schema.repeat.containsKey("daily") -> {
                repeatType = "daily"
                weekly = List(7) { false }
                monthly = List(31) { false }
                days = listOf()
            }
            schema.repeat.containsKey("weekly") -> {
                repeatType = "weekly"
                weekly = schema.repeat["weekly"]!!.jsonArray.map { it.jsonPrimitive.boolean }
                monthly = List(31) { false }
                days = listOf()
            }
            schema.repeat.containsKey("2week") -> {
                repeatType = "2week"
                weekly = schema.repeat["2week"]!!.jsonArray.map { it.jsonPrimitive.boolean }
                monthly = List(31) { false }
                days = listOf()
            }
            schema.repeat.containsKey("4week") -> {
                repeatType = "4week"
                weekly = schema.repeat["4week"]!!.jsonArray.map { it.jsonPrimitive.boolean }
                monthly = List(31) { false }
                days = listOf()
            }
            schema.repeat.containsKey("monthly") -> {
                repeatType = "monthly"
                weekly = List(7) { false }
                monthly = schema.repeat["monthly"]!!.jsonArray.map { it.jsonPrimitive.boolean }
                days = listOf()
            }
            schema.repeat.containsKey("days") -> {
                repeatType = "days"
                weekly = List(7) { false }
                monthly = List(31) { false }
                days = schema.repeat["days"]!!.jsonArray.map { it.jsonPrimitive.contentOrNull ?: "" }
            }
        }
    }

    private fun buildRequest(): TaskSchemaRequest {
        val repeat = when (repeatType) {
            "daily" -> JsonObject(mapOf("daily" to JsonPrimitive(true)))
            "weekly" -> JsonObject(mapOf("weekly" to buildJsonArray { weekly.forEach { add(JsonPrimitive(it)) } }))
            "2week" -> JsonObject(mapOf("2week" to buildJsonArray { weekly.forEach { add(JsonPrimitive(it)) } }))
            "4week" -> JsonObject(mapOf("4week" to buildJsonArray { weekly.forEach { add(JsonPrimitive(it)) } }))
            "monthly" -> JsonObject(mapOf("monthly" to buildJsonArray { monthly.forEach { add(JsonPrimitive(it)) } }))
            "days" -> JsonObject(mapOf("days" to buildJsonArray { days.filter { it.isNotBlank() }.forEach { add(JsonPrimitive(it)) } }))
            else -> null
        }

        return TaskSchemaRequest(
            name = name,
            status = status,
            taskStatus = taskStatus,
            date = if (repeatType == "none" && date.isNotBlank()) date else null,
            repeat = repeat,
            start = if (repeatType != "none" && start.isNotBlank()) start else null,
            end = if (repeatType != "none" && end.isNotBlank()) end else null,
        )
    }
}
