package com.example.elva.ui.health

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import javax.inject.Inject

@HiltViewModel
class HealthDashboardViewModel @Inject constructor(
    private val healthRepository: HealthRepository
) : ViewModel() {

    private val _state = MutableStateFlow(HealthDashboardState())
    val state: StateFlow<HealthDashboardState> = _state.asStateFlow()

    init {
        loadHealthData()
    }

    fun loadHealthData() {
        viewModelScope.launch {
            _state.value = _state.value.copy(isLoading = true)

            // Загрузка данных периода
            val lastPeriod = healthRepository.getLastPeriod()
            val (cycleDay, nextPeriodDays, nextPeriodDate) = calculatePeriodInfo(lastPeriod)

            // Загрузка калорий
            val todayCalories = healthRepository.getTodayCalories()
            val calorieGoal = healthRepository.getCalorieGoal()
            val caloriesConsumed = todayCalories?.consumed ?: 0
            val caloriesPercent = if (calorieGoal > 0)
                ((caloriesConsumed.toFloat() / calorieGoal) * 100).toInt().coerceIn(0, 100)
            else 0

            // Загрузка воды
            val todayWater = healthRepository.getTodayWater()
            val waterGoal = healthRepository.getWaterGoal()
            val waterConsumed = todayWater?.consumed ?: 0
            val waterPercent = if (waterGoal > 0)
                ((waterConsumed.toFloat() / waterGoal) * 100).toInt().coerceIn(0, 100)
            else 0

            // Загрузка веса
            val latestWeight = healthRepository.getLatestWeight()
            val weightGoal = healthRepository.getWeightGoal()
            val weightEntries = healthRepository.getWeightEntries()
            val weightChange = if (weightEntries.size >= 2) {
                val current = weightEntries.last().weight
                val previous = weightEntries[weightEntries.size - 2].weight
                current - previous
            } else 0f

            // Загрузка сна
            val lastSleep = healthRepository.getLastNightSleep()
            val sleepGoal = healthRepository.getSleepGoal()
            val sleepHours = lastSleep?.hours ?: 0f
            val sleepPercent = if (sleepGoal > 0)
                ((sleepHours / sleepGoal) * 100).toInt().coerceIn(0, 100)
            else 0

            _state.value = HealthDashboardState(
                currentCycleDay = cycleDay,
                nextPeriodDays = nextPeriodDays,
                nextPeriodDate = nextPeriodDate,
                caloriesConsumed = caloriesConsumed,
                caloriesGoal = calorieGoal,
                caloriesPercent = caloriesPercent,
                waterConsumed = waterConsumed,
                waterGoal = waterGoal,
                waterPercent = waterPercent,
                currentWeight = latestWeight?.weight,
                weightGoal = weightGoal,
                weightChange = weightChange,
                sleepHours = sleepHours,
                sleepGoal = sleepGoal,
                sleepPercent = sleepPercent,
                sleepQuality = lastSleep?.quality ?: SleepQuality.GOOD,
                isLoading = false
            )
        }
    }

    fun updateCalories(consumed: Int) {
        viewModelScope.launch {
            val goal = healthRepository.getCalorieGoal()
            healthRepository.saveCalorieEntry(
                CalorieEntry(consumed = consumed, goal = goal)
            )
            loadHealthData()
        }
    }

    fun updateWater(consumed: Int) {
        viewModelScope.launch {
            val goal = healthRepository.getWaterGoal()
            healthRepository.saveWaterEntry(
                WaterEntry(consumed = consumed, goal = goal)
            )
            loadHealthData()
        }
    }

    fun updateWeight(weight: Float) {
        viewModelScope.launch {
            val goal = healthRepository.getWeightGoal()
            healthRepository.saveWeightEntry(
                WeightEntry(weight = weight, goal = goal)
            )
            loadHealthData()
        }
    }

    fun updateSleep(hours: Float, quality: SleepQuality) {
        viewModelScope.launch {
            val goal = healthRepository.getSleepGoal()
            healthRepository.saveSleepEntry(
                SleepEntry(hours = hours, goal = goal, quality = quality)
            )
            loadHealthData()
        }
    }

    fun setCalorieGoal(goal: Int) {
        viewModelScope.launch {
            healthRepository.setCalorieGoal(goal)
            loadHealthData()
        }
    }

    fun setWaterGoal(goal: Int) {
        viewModelScope.launch {
            healthRepository.setWaterGoal(goal)
            loadHealthData()
        }
    }

    fun setWeightGoal(goal: Float) {
        viewModelScope.launch {
            healthRepository.setWeightGoal(goal)
            loadHealthData()
        }
    }

    fun setSleepGoal(goal: Float) {
        viewModelScope.launch {
            healthRepository.setSleepGoal(goal)
            loadHealthData()
        }
    }

    private fun calculatePeriodInfo(lastPeriod: PeriodData?): Triple<Int, Int, String> {
        if (lastPeriod == null) {
            return Triple(0, 0, "—")
        }

        val calendar = Calendar.getInstance()
        val today = calendar.timeInMillis
        val startDate = lastPeriod.startDate

        // Вычисляем день цикла
        val daysDiff = ((today - startDate) / (24 * 60 * 60 * 1000)).toInt()
        val cycleDay = (daysDiff % lastPeriod.cycleLength) + 1

        // Вычисляем дни до следующего периода
        val daysUntilNext = lastPeriod.cycleLength - cycleDay + 1

        // Вычисляем дату следующего периода
        calendar.timeInMillis = startDate
        calendar.add(Calendar.DAY_OF_MONTH, lastPeriod.cycleLength)
        val dateFormat = SimpleDateFormat("d MMMM", Locale("ru"))
        val nextDateString = dateFormat.format(calendar.time)

        return Triple(cycleDay, daysUntilNext, nextDateString)
    }

    fun openCalendar() {
        // Навигация к календарю будет обработана во фрагменте
    }
}

