package com.example.elva.data.local

import android.content.Context
import android.content.SharedPreferences
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.time.LocalDate
import java.time.LocalDateTime
import com.example.elva.data.models.health.*
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class HealthDataStore @Inject constructor(
    @ApplicationContext context: Context
) {
    private val prefs: SharedPreferences = context.getSharedPreferences("health_data", Context.MODE_PRIVATE)
    private val gson = Gson()

    // Period tracking
    fun savePeriods(periods: List<Period>) {
        val json = gson.toJson(periods)
        prefs.edit().putString("periods", json).apply()
    }

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

    fun addPeriod(period: Period) {
        val periods = getPeriods().toMutableList()
        periods.add(period.copy(id = System.currentTimeMillis()))
        savePeriods(periods)
    }

    fun updatePeriod(period: Period) {
        val periods = getPeriods().toMutableList()
        val index = periods.indexOfFirst { it.id == period.id }
        if (index != -1) {
            periods[index] = period
            savePeriods(periods)
        }
    }

    fun deletePeriod(periodId: Long) {
        val periods = getPeriods().filter { it.id != periodId }
        savePeriods(periods)
    }

    // Water intake
    fun saveWaterIntakes(intakes: List<WaterIntake>) {
        val json = gson.toJson(intakes)
        prefs.edit().putString("water_intakes", json).apply()
    }

    fun getWaterIntakes(): List<WaterIntake> {
        val json = prefs.getString("water_intakes", null) ?: return emptyList()
        val type = object : TypeToken<List<WaterIntake>>() {}.type
        return gson.fromJson(json, type)
    }

    fun addWater(date: LocalDate, amountMl: Int) {
        val intakes = getWaterIntakes().toMutableList()
        val existing = intakes.find { it.date == date }
        if (existing != null) {
            intakes.removeIf { it.date == date }
            intakes.add(existing.copy(amountMl = existing.amountMl + amountMl))
        } else {
            intakes.add(WaterIntake(
                id = System.currentTimeMillis(),
                date = date,
                amountMl = amountMl
            ))
        }
        saveWaterIntakes(intakes)
    }

    fun getWaterGoal(): Int = prefs.getInt("water_goal", 2000)
    fun setWaterGoal(goalMl: Int) = prefs.edit().putInt("water_goal", goalMl).apply()

    // Calories
    fun saveCalorieEntries(entries: List<CalorieEntry>) {
        val json = gson.toJson(entries)
        prefs.edit().putString("calorie_entries", json).apply()
    }

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

    fun addCalorieEntry(entry: CalorieEntry) {
        val entries = getCalorieEntries().toMutableList()
        entries.add(entry.copy(id = System.currentTimeMillis()))
        saveCalorieEntries(entries)
    }

    fun deleteCalorieEntry(entryId: Long) {
        val entries = getCalorieEntries().filter { it.id != entryId }
        saveCalorieEntries(entries)
    }

    fun getCalorieGoal(): CalorieGoal {
        val dailyGoal = prefs.getInt("calorie_goal", 2000)
        val protein = prefs.getInt("protein_goal", 0)
        val carbs = prefs.getInt("carbs_goal", 0)
        val fats = prefs.getInt("fats_goal", 0)
        return CalorieGoal(dailyGoal, protein, carbs, fats)
    }

    fun setCalorieGoal(goal: CalorieGoal) {
        prefs.edit()
            .putInt("calorie_goal", goal.dailyGoal)
            .putInt("protein_goal", goal.protein)
            .putInt("carbs_goal", goal.carbs)
            .putInt("fats_goal", goal.fats)
            .apply()
    }

    // Weight
    fun saveWeightEntries(entries: List<WeightEntry>) {
        val json = gson.toJson(entries)
        prefs.edit().putString("weight_entries", json).apply()
    }

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

    fun addWeightEntry(entry: WeightEntry) {
        val entries = getWeightEntries().toMutableList()
        entries.add(entry.copy(id = System.currentTimeMillis()))
        saveWeightEntries(entries)
    }

    fun deleteWeightEntry(entryId: Long) {
        val entries = getWeightEntries().filter { it.id != entryId }
        saveWeightEntries(entries)
    }

    // Sleep
    fun saveSleepEntries(entries: List<SleepEntry>) {
        val json = gson.toJson(entries)
        prefs.edit().putString("sleep_entries", json).apply()
    }

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

    fun addSleepEntry(entry: SleepEntry) {
        val entries = getSleepEntries().toMutableList()
        entries.add(entry.copy(id = System.currentTimeMillis()))
        saveSleepEntries(entries)
    }

    fun deleteSleepEntry(entryId: Long) {
        val entries = getSleepEntries().filter { it.id != entryId }
        saveSleepEntries(entries)
    }

    fun getSleepGoal(): Float = prefs.getFloat("sleep_goal", 8f)
    fun setSleepGoal(hours: Float) = prefs.edit().putFloat("sleep_goal", hours).apply()

    // Journal
    fun saveJournalEntries(entries: List<HealthJournalEntry>) {
        val json = gson.toJson(entries)
        prefs.edit().putString("journal_entries", json).apply()
    }

    fun getJournalEntries(): List<HealthJournalEntry> {
        val json = prefs.getString("journal_entries", null) ?: return emptyList()
        val type = object : TypeToken<List<HealthJournalEntry>>() {}.type
        return gson.fromJson(json, type)
    }

    fun addJournalEntry(entry: HealthJournalEntry) {
        val entries = getJournalEntries().toMutableList()
        entries.add(entry.copy(id = System.currentTimeMillis()))
        saveJournalEntries(entries)
    }

    fun deleteJournalEntry(entryId: Long) {
        val entries = getJournalEntries().filter { it.id != entryId }
        saveJournalEntries(entries)
    }

    // Helper methods for today's data
    fun getTodayWaterIntake(): Int {
        val today = LocalDate.now()
        return getWaterIntakes().find { it.date == today }?.amountMl ?: 0
    }

    fun getTodayCalories(): Int {
        val today = LocalDate.now()
        return getCalorieEntries()
            .filter { it.date == today }
            .sumOf { it.calories }
    }

    fun getTodaySleep(): SleepEntry? {
        val today = LocalDate.now()
        return getSleepEntries().find { it.date == today }
    }

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

