package ru.forbion.f7cloud.feature.calendar

import android.content.Context
import java.io.File
import java.security.MessageDigest

/**
 * Дисковый кэш «сырых» REPORT-ответов CalDAV (события по диапазону), ключуемый
 * CTag'ом календаря: CTag не изменился → события читаются с диска, сеть не трогаем.
 *
 * Храним именно сырой XML (а не сериализованные модели) — переиспользуем боевой
 * парсер CalDavClient и не заводим хрупкий JSON-маппинг ~20 полей события.
 * Формат файла: первая строка — CTag на момент загрузки, дальше XML.
 */
class CalendarEventsCache(private val dir: File) {

    constructor(context: Context) : this(File(context.cacheDir, "caldav_events"))

    /** XML событий, если кэш есть и его CTag совпадает с текущим; иначе null. */
    fun get(accountKey: String, calendarHref: String, rangeKey: String, ctag: String): String? {
        if (ctag.isBlank()) return null
        val f = entryFile(accountKey, calendarHref, rangeKey)
        if (!f.isFile) return null
        return runCatching {
            val text = f.readText()
            val nl = text.indexOf('\n')
            if (nl > 0 && text.substring(0, nl) == ctag) text.substring(nl + 1) else null
        }.getOrNull()
    }

    fun put(accountKey: String, calendarHref: String, rangeKey: String, ctag: String, xml: String) {
        if (ctag.isBlank()) return
        runCatching {
            dir.mkdirs()
            entryFile(accountKey, calendarHref, rangeKey).writeText("$ctag\n$xml")
            prune()
        }
    }

    /** Чистка устаревших записей (диапазоны уезжают со временем — файлы копятся). */
    private fun prune(maxAgeMillis: Long = MAX_AGE_MILLIS) {
        val now = System.currentTimeMillis()
        dir.listFiles()?.forEach { f ->
            if (now - f.lastModified() > maxAgeMillis) f.delete()
        }
    }

    private fun entryFile(accountKey: String, calendarHref: String, rangeKey: String): File =
        File(dir, md5("$accountKey|$calendarHref|$rangeKey") + ".xml")

    private fun md5(s: String): String =
        MessageDigest.getInstance("MD5").digest(s.toByteArray())
            .joinToString("") { "%02x".format(it) }

    private companion object {
        const val MAX_AGE_MILLIS = 30L * 24 * 3600 * 1000 // 30 дней
    }
}
