//
//  LocationStateStore.swift
//  suixinkan
//
//  Created by Codex on 2026/6/29.
//

import Foundation

/// 位置上报本地状态存储，持久化在线状态、过期时间、上次上报时间和提醒设置。
final class LocationStateStore {
    static let onlineDurationSeconds = 7200
    /// 区分 Unix 时间戳与剩余秒数的阈值。
    private static let expireTimestampThreshold = 1_000_000_000

    private let defaults: UserDefaults
    private let lastReportTimeKey = "key_last_location_report_time"
    private let expireTimeKey = "key_location_expire_time"
    private let onlineStatusKey = "key_online_status"
    private let reminderMinutesKey = "key_location_reminder_minutes"

    /// 初始化位置状态存储，并允许测试注入独立 UserDefaults。
    init(defaults: UserDefaults = .standard) {
        self.defaults = defaults
    }

    /// 读取是否在线。
    func loadOnlineStatus() -> Bool {
        defaults.bool(forKey: onlineStatusKey)
    }

    /// 保存是否在线。
    func saveOnlineStatus(_ isOnline: Bool) {
        defaults.set(isOnline, forKey: onlineStatusKey)
    }

    /// 读取上次上报时间戳（毫秒）。
    func loadLastReportTime() -> TimeInterval {
        defaults.double(forKey: lastReportTimeKey)
    }

    /// 保存上次上报时间戳（毫秒）。
    func saveLastReportTime(_ timestamp: TimeInterval) {
        defaults.set(timestamp, forKey: lastReportTimeKey)
    }

    /// 清除上次上报时间。
    func clearLastReportTime() {
        defaults.removeObject(forKey: lastReportTimeKey)
    }

    /// 读取服务端返回的过期 Unix 时间戳（秒）。
    func loadExpireTime() -> Int {
        defaults.integer(forKey: expireTimeKey)
    }

    /// 保存服务端返回的过期 Unix 时间戳（秒）。
    func saveExpireTime(_ timestamp: Int) {
        defaults.set(timestamp, forKey: expireTimeKey)
    }

    /// 清除过期时间。
    func clearExpireTime() {
        defaults.removeObject(forKey: expireTimeKey)
    }

    /// 读取提前提醒分钟数，默认 0 表示不提醒。
    func loadReminderMinutes() -> Int {
        guard defaults.object(forKey: reminderMinutesKey) != nil else { return 0 }
        return defaults.integer(forKey: reminderMinutesKey)
    }

    /// 保存提前提醒分钟数。
    func saveReminderMinutes(_ minutes: Int) {
        defaults.set(minutes, forKey: reminderMinutesKey)
    }

    /// 将服务端 expired 规范化为过期 Unix 时间戳（秒）。
    func normalizedExpireTimestamp(from raw: Int, now: Date = Date()) -> Int {
        guard raw > 0 else {
            return Int(now.timeIntervalSince1970) + Self.onlineDurationSeconds
        }
        if raw > Self.expireTimestampThreshold {
            return raw
        }
        return Int(now.timeIntervalSince1970) + raw
    }

    /// 根据过期时间戳计算剩余倒计时秒数；已过期返回 0。
    func remainingSeconds(untilExpireTime expireTime: Int, now: Date = Date()) -> Int {
        guard expireTime > 0 else { return 0 }
        let nowSeconds = Int(now.timeIntervalSince1970)
        return max(0, expireTime - nowSeconds)
    }

    /// 根据上次上报时间计算剩余倒计时秒数；已过期返回 0。仅用于无过期时间戳时的兼容恢复。
    func remainingSeconds(since anchorTime: TimeInterval, now: Date = Date()) -> Int {
        let elapsed = now.timeIntervalSince1970 * 1000 - anchorTime
        let remainingMillis = Double(Self.onlineDurationSeconds) * 1000 - elapsed
        guard remainingMillis > 0 else { return 0 }
        return Int(remainingMillis / 1000)
    }

    /// 判断上次上报是否仍在 2 小时在线窗口内。
    func isWithinOnlineWindow(since anchorTime: TimeInterval, now: Date = Date()) -> Bool {
        remainingSeconds(since: anchorTime, now: now) > 0
    }
}
