//
//  HomeLocationStateStore.swift
//  suixinkan
//

import Foundation

/// 首页在线状态与 2 小时倒计时存储，对齐 Android `LocationStateRepository`。
final class HomeLocationStateStore {

    static let shared = HomeLocationStateStore(store: .shared)

    static let onlineDurationMillis: Int64 = 2 * 60 * 60 * 1000

    private(set) var isOnline = false
    private(set) var elapsedSeconds: Int64 = 0
    private(set) var nextReportCountdownSeconds: Int64 = 0
    private(set) var reminderMinutes = 0

    private let store: AppStore
    private var countdownTask: Task<Void, Never>?
    private var anchorTimestamp: Int64?
    private var observers: [ObjectIdentifier: StateObserver] = [:]

    init(store: AppStore = .shared) {
        self.store = store
        reminderMinutes = store.location.reminderMinutes
        isOnline = store.location.onlineStatus
    }

    deinit {
        countdownTask?.cancel()
    }

    /// 监听状态变化，允许首页与独立位置上报页同时刷新。
    func observe(_ owner: AnyObject, handler: @escaping () -> Void) {
        observers[ObjectIdentifier(owner)] = StateObserver(owner: owner, handler: handler)
    }

    /// 移除指定监听者。
    func removeObserver(_ owner: AnyObject) {
        observers.removeValue(forKey: ObjectIdentifier(owner))
    }

    /// 启动时恢复在线倒计时。
    func restoreStateIfNeeded() {
        reminderMinutes = store.location.reminderMinutes
        guard store.location.onlineStatus else {
            isOnline = false
            stopCountdown()
            notifyChange()
            return
        }
        let lastTime = store.location.lastReportTime
        guard lastTime > 0 else {
            isOnline = false
            store.location.onlineStatus = false
            store.location.clearLastReportTime()
            stopCountdown()
            notifyChange()
            return
        }

        let now = Int64(Date().timeIntervalSince1970 * 1000)
        let elapsed = now - lastTime
        if elapsed >= Self.onlineDurationMillis {
            updateOnlineStatus(false)
            store.location.clearLastReportTime()
            notifyChange()
            return
        }

        anchorTimestamp = lastTime
        let remaining = Self.onlineDurationMillis - elapsed
        elapsedSeconds = max(0, elapsed / 1000)
        nextReportCountdownSeconds = max(0, remaining / 1000)
        startCountdown(anchorTime: lastTime)
        notifyChange()
    }

    /// 更新在线状态并持久化。
    func updateOnlineStatus(_ online: Bool) {
        isOnline = online
        store.location.onlineStatus = online
        if !online {
            stopCountdown()
            store.location.clearLastReportTime()
        }
        notifyChange()
    }

    /// 更新提醒分钟数。
    func updateReminderMinutes(_ minutes: Int) {
        reminderMinutes = minutes
        store.location.reminderMinutes = minutes
        notifyChange()
    }

    /// 开始新的位置上报会话。
    func startLocationReport(at timestamp: Int64 = Int64(Date().timeIntervalSince1970 * 1000)) {
        anchorTimestamp = timestamp
        store.location.lastReportTime = timestamp
        isOnline = true
        store.location.onlineStatus = true
        elapsedSeconds = 0
        nextReportCountdownSeconds = Self.onlineDurationMillis / 1000
        startCountdown(anchorTime: timestamp)
        notifyChange()
    }

    var countdownDisplayText: String {
        formattedCountdown(from: nextReportCountdownSeconds)
    }

    /// Android 独立页倒计时格式 `H:MM:SS`。
    var countdownDisplayTextSingleHour: String {
        formattedCountdownSingleHour(from: nextReportCountdownSeconds)
    }

    /// 格式化倒计时文本 `HH:MM:SS`。
    func formattedCountdown(from seconds: Int64) -> String {
        let hours = seconds / 3600
        let minutes = (seconds % 3600) / 60
        let secs = seconds % 60
        return String(format: "%02d:%02d:%02d", hours, minutes, secs)
    }

    /// 格式化倒计时文本 `H:MM:SS`。
    func formattedCountdownSingleHour(from seconds: Int64) -> String {
        let hours = seconds / 3600
        let minutes = (seconds % 3600) / 60
        let secs = seconds % 60
        return String(format: "%d:%02d:%02d", hours, minutes, secs)
    }

    /// 是否到达提前提醒窗口。
    func shouldTriggerTimeoutReminder() -> Bool {
        guard reminderMinutes > 0, isOnline else { return false }
        let reminderSeconds = Int64(reminderMinutes * 60)
        return nextReportCountdownSeconds > 0 && nextReportCountdownSeconds <= reminderSeconds
    }

    private func startCountdown(anchorTime: Int64) {
        countdownTask?.cancel()
        countdownTask = Task { [weak self] in
            while !Task.isCancelled {
                guard let self else { return }
                guard self.isOnline else { return }

                let now = Int64(Date().timeIntervalSince1970 * 1000)
                let elapsed = now - anchorTime
                let remaining = Self.onlineDurationMillis - elapsed
                let elapsedSeconds = max(0, elapsed / 1000)

                self.elapsedSeconds = elapsedSeconds
                if remaining <= 0 {
                    self.nextReportCountdownSeconds = 0
                    self.updateOnlineStatus(false)
                    self.store.location.clearLastReportTime()
                    return
                }
                self.nextReportCountdownSeconds = max(0, remaining / 1000)
                self.notifyChange()
                try? await Task.sleep(nanoseconds: 1_000_000_000)
            }
        }
    }

    private func stopCountdown() {
        countdownTask?.cancel()
        countdownTask = nil
        anchorTimestamp = nil
        elapsedSeconds = 0
        nextReportCountdownSeconds = 0
    }

    private func notifyChange() {
        observers = observers.filter { $0.value.owner != nil }
        observers.values.forEach { $0.handler() }
    }
}

private final class StateObserver {
    weak var owner: AnyObject?
    let handler: () -> Void

    init(owner: AnyObject, handler: @escaping () -> Void) {
        self.owner = owner
        self.handler = handler
    }
}
