package com.example.elva.ui.health

import android.content.Context
import android.content.SharedPreferences
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Репозиторий для работы с данными здоровья
 */
@Singleton
class HealthRepository @Inject constructor(
    @ApplicationContext private val context: Context
) {
    private val prefs: SharedPreferences =
        context.getSharedPreferences("health_data", Context.MODE_PRIVATE)
    private val gson = Gson()

    // Калории
    fun saveCalorieEntry(entry: CalorieEntry) {
        val entries = getCalorieEntries().toMutableList()
        entries.add(entry)
        saveCalorieEntries(entries)
    }

    fun getCalorieEntries(): List<CalorieEntry> {
        val json = prefs.getString("calorie_entries", "[]") ?: "[]"
        val type = object : TypeToken<List<CalorieEntry>>() {}.type
        return gson.fromJson(json, type)
    }

    private fun saveCalorieEntries(entries: List<CalorieEntry>) {
        prefs.edit().putString("calorie_entries", gson.toJson(entries)).apply()
    }

    fun getTodayCalories(): CalorieEntry? {
        return getCalorieEntries()
            .filter { isToday(it.timestamp) }
            .maxByOrNull { it.timestamp }
    }

    // Вода
    fun saveWaterEntry(entry: WaterEntry) {
        val entries = getWaterEntries().toMutableList()
        entries.add(entry)
        saveWaterEntries(entries)
    }

    fun getWaterEntries(): List<WaterEntry> {
        val json = prefs.getString("water_entries", "[]") ?: "[]"
        val type = object : TypeToken<List<WaterEntry>>() {}.type
        return gson.fromJson(json, type)
    }

    private fun saveWaterEntries(entries: List<WaterEntry>) {
        prefs.edit().putString("water_entries", gson.toJson(entries)).apply()
    }

    fun getTodayWater(): WaterEntry? {
        return getWaterEntries()
            .filter { isToday(it.timestamp) }
            .maxByOrNull { it.timestamp }
    }

    // Вес
    fun saveWeightEntry(entry: WeightEntry) {
        val entries = getWeightEntries().toMutableList()
        entries.add(entry)
        saveWeightEntries(entries)
    }

    fun getWeightEntries(): List<WeightEntry> {
        val json = prefs.getString("weight_entries", "[]") ?: "[]"
        val type = object : TypeToken<List<WeightEntry>>() {}.type
        return gson.fromJson(json, type)
    }

    private fun saveWeightEntries(entries: List<WeightEntry>) {
        prefs.edit().putString("weight_entries", gson.toJson(entries)).apply()
    }

    fun getLatestWeight(): WeightEntry? {
        return getWeightEntries().maxByOrNull { it.timestamp }
    }

    // Сон
    fun saveSleepEntry(entry: SleepEntry) {
        val entries = getSleepEntries().toMutableList()
        entries.add(entry)
        saveSleepEntries(entries)
    }

    fun getSleepEntries(): List<SleepEntry> {
        val json = prefs.getString("sleep_entries", "[]") ?: "[]"
        val type = object : TypeToken<List<SleepEntry>>() {}.type
        return gson.fromJson(json, type)
    }

    private fun saveSleepEntries(entries: List<SleepEntry>) {
        prefs.edit().putString("sleep_entries", gson.toJson(entries)).apply()
    }

    fun getLastNightSleep(): SleepEntry? {
        return getSleepEntries()
            .filter { isYesterday(it.timestamp) || isToday(it.timestamp) }
            .maxByOrNull { it.timestamp }
    }

    // Заметки
    fun saveNote(note: HealthNote) {
        val notes = getNotes().toMutableList()
        notes.add(note)
        saveNotes(notes)
    }

    fun getNotes(): List<HealthNote> {
        val json = prefs.getString("health_notes", "[]") ?: "[]"
        val type = object : TypeToken<List<HealthNote>>() {}.type
        return gson.fromJson(json, type)
    }

    private fun saveNotes(notes: List<HealthNote>) {
        prefs.edit().putString("health_notes", gson.toJson(notes)).apply()
    }

    fun deleteNote(noteId: String) {
        val notes = getNotes().filter { it.id != noteId }
        saveNotes(notes)
    }

    // Периоды
    fun savePeriod(period: PeriodData) {
        val periods = getPeriods().toMutableList()
        periods.add(period)
        savePeriods(periods)
    }

    fun getPeriods(): List<PeriodData> {
        val json = prefs.getString("periods", "[]") ?: "[]"
        val type = object : TypeToken<List<PeriodData>>() {}.type
        return gson.fromJson(json, type)
    }

    private fun savePeriods(periods: List<PeriodData>) {
        prefs.edit().putString("periods", gson.toJson(periods)).apply()
    }

    fun getLastPeriod(): PeriodData? {
        return getPeriods().maxByOrNull { it.startDate }
    }

    // Цели
    fun setCalorieGoal(goal: Int) {
        prefs.edit().putInt("calorie_goal", goal).apply()
    }

    fun getCalorieGoal(): Int = prefs.getInt("calorie_goal", 2000)

    fun setWaterGoal(goal: Int) {
        prefs.edit().putInt("water_goal", goal).apply()
    }

    fun getWaterGoal(): Int = prefs.getInt("water_goal", 2000)

    fun setWeightGoal(goal: Float) {
        prefs.edit().putFloat("weight_goal", goal).apply()
    }

    fun getWeightGoal(): Float? {
        val goal = prefs.getFloat("weight_goal", -1f)
        return if (goal > 0) goal else null
    }

    fun setSleepGoal(goal: Float) {
        prefs.edit().putFloat("sleep_goal", goal).apply()
    }

    fun getSleepGoal(): Float = prefs.getFloat("sleep_goal", 8f)

    // Вспомогательные функции
    private fun isToday(timestamp: Long): Boolean {
        val cal1 = java.util.Calendar.getInstance().apply { timeInMillis = timestamp }
        val cal2 = java.util.Calendar.getInstance()
        return cal1.get(java.util.Calendar.YEAR) == cal2.get(java.util.Calendar.YEAR) &&
                cal1.get(java.util.Calendar.DAY_OF_YEAR) == cal2.get(java.util.Calendar.DAY_OF_YEAR)
    }

    private fun isYesterday(timestamp: Long): Boolean {
        val cal1 = java.util.Calendar.getInstance().apply { timeInMillis = timestamp }
        val cal2 = java.util.Calendar.getInstance().apply { add(java.util.Calendar.DAY_OF_YEAR, -1) }
        return cal1.get(java.util.Calendar.YEAR) == cal2.get(java.util.Calendar.YEAR) &&
                cal1.get(java.util.Calendar.DAY_OF_YEAR) == cal2.get(java.util.Calendar.DAY_OF_YEAR)
    }
}

