package com.doctate.watch.domain

import kotlinx.coroutines.flow.StateFlow

/**
 * Per-case marker store. Single source of truth for the case list shown in
 * Activity, Tile and Complication. Mirrors `doctate-desktop::CaseStore`
 * (Rust) — the asymmetric merge/reconcile design is the load-bearing piece:
 *
 * - [mergeServerSnapshot] only adds/updates. `/api/oneliners` is a sliding
 *   window, so "missing" means nothing on its own.
 * - [reconcileWithServerSnapshot] removes synced markers the server no
 *   longer reports, scoped to the window it covers. Pending markers are
 *   never touched — losing one would silently erase a recording.
 */
interface CaseStore {
    /** Reactive snapshot, sorted by `lastActivityAt` desc. */
    val casesFlow: StateFlow<List<CaseEntry>>

    /** Snapshot accessor for non-suspending contexts (Tile, Complication). */
    val currentCase: CaseEntry? get() = casesFlow.value.firstOrNull()

    /** Append a new case the client itself just started. Returns the new id. */
    suspend fun createLocal(now: Long = System.currentTimeMillis()): String

    /** Bump `lastActivityAt`. Creates the marker if missing. */
    suspend fun markActivity(caseId: String, now: Long = System.currentTimeMillis())

    /** Flip `syncedToServer` to true after a successful upload ACK. No-op if absent. */
    suspend fun markSynced(caseId: String)

    /** Apply a doctor's manual oneliner override locally (optimistic UI). */
    suspend fun setOnelinerLocal(caseId: String, state: OnelinerState)

    /**
     * Apply a server `/api/oneliners` response: insert/update each entry,
     * never delete. Server's oneliner + timestamps win, except
     * `lastActivityAt` keeps whichever (local vs. server) is newer, and a
     * locally-set `Manual` oneliner sticks against non-Manual server states.
     */
    suspend fun mergeServerSnapshot(response: OnelinersResponse)

    /**
     * Remove synced markers inside the response's window that the server
     * no longer lists. Returns count removed. Pending markers and markers
     * outside the window are preserved.
     */
    suspend fun reconcileWithServerSnapshot(response: OnelinersResponse): Int

    /** Drop synced markers older than `cutoffMs`. Returns count removed. */
    suspend fun cleanupStale(cutoffMs: Long): Int

    /** Wipe everything (config change, account switch). */
    suspend fun clearAll()
}
