//
//  HomeLocationStateStoreTests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

/// 首页在线状态存储测试。
final class HomeLocationStateStoreTests: XCTestCase {

    private var appStore: AppStore!
    private var defaults: UserDefaults!

    override func setUp() {
        defaults = UserDefaults(suiteName: "HomeLocationStateStoreTests")!
        defaults.removePersistentDomain(forName: "HomeLocationStateStoreTests")
        appStore = AppStore(defaults: defaults)
        appStore.session.userId = "1001"
        appStore.session.accountType = .scenicUser
    }

    override func tearDown() {
        appStore.logout()
        super.tearDown()
    }

    func testExpiredOnlineSessionIsClearedOnRestore() {
        let expiredTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - HomeLocationStateStore.onlineDurationMillis - 1_000
        appStore.location.onlineStatus = true
        appStore.location.lastReportTime = expiredTimestamp

        let stateStore = HomeLocationStateStore(store: appStore)
        stateStore.restoreStateIfNeeded()

        XCTAssertFalse(stateStore.isOnline)
        XCTAssertFalse(appStore.location.onlineStatus)
        XCTAssertEqual(appStore.location.lastReportTime, 0)
    }

    func testActiveOnlineSessionRestoresCountdown() {
        let recentTimestamp = Int64(Date().timeIntervalSince1970 * 1000) - 60_000
        appStore.location.onlineStatus = true
        appStore.location.lastReportTime = recentTimestamp

        let stateStore = HomeLocationStateStore(store: appStore)
        stateStore.restoreStateIfNeeded()

        XCTAssertTrue(stateStore.isOnline)
        XCTAssertGreaterThan(stateStore.nextReportCountdownSeconds, 0)
    }

    func testFormattedCountdownText() {
        let stateStore = HomeLocationStateStore(store: appStore)
        XCTAssertEqual(stateStore.formattedCountdown(from: 3661), "01:01:01")
    }

    func testShouldTriggerTimeoutReminderWithinWindow() {
        appStore.location.reminderMinutes = 10
        let stateStore = HomeLocationStateStore(store: appStore)
        stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
        stateStore.updateReminderMinutes(10)
        // Force countdown into reminder window via reflection of internal state is not available;
        // verify helper with manual expectation on threshold logic.
        XCTAssertFalse(stateStore.shouldTriggerTimeoutReminder())
    }

    func testMultipleObserversReceiveStateChanges() {
        let stateStore = HomeLocationStateStore(store: appStore)
        let firstOwner = StateObserverOwner()
        let secondOwner = StateObserverOwner()
        var firstChangeCount = 0
        var secondChangeCount = 0

        stateStore.observe(firstOwner) { firstChangeCount += 1 }
        stateStore.observe(secondOwner) { secondChangeCount += 1 }
        stateStore.updateReminderMinutes(5)

        XCTAssertEqual(firstChangeCount, 1)
        XCTAssertEqual(secondChangeCount, 1)

        stateStore.removeObserver(firstOwner)
        stateStore.updateReminderMinutes(10)

        XCTAssertEqual(firstChangeCount, 1)
        XCTAssertEqual(secondChangeCount, 2)
    }

    func testViewModelsShareReminderMinutesWhenUsingSameStateStore() {
        let stateStore = HomeLocationStateStore(store: appStore)
        let homeViewModel = HomeViewModel(appStore: appStore, locationStateStore: stateStore)
        let reportViewModel = LocationReportViewModel(
            locationStateStore: stateStore,
            locationProvider: MockLocationProvider()
        )

        homeViewModel.updateReminderMinutes(15)

        XCTAssertEqual(reportViewModel.reminderMinutes, 15)

        reportViewModel.updateReminderMinutes(5)

        XCTAssertEqual(homeViewModel.reminderMinutes, 5)
    }

    func testViewModelsShareOnlineStateWhenUsingSameStateStore() {
        let stateStore = HomeLocationStateStore(store: appStore)
        let homeViewModel = HomeViewModel(appStore: appStore, locationStateStore: stateStore)
        let reportViewModel = LocationReportViewModel(
            locationStateStore: stateStore,
            locationProvider: MockLocationProvider()
        )

        stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))

        XCTAssertTrue(homeViewModel.isOnline)
        XCTAssertTrue(reportViewModel.isOnline)
        XCTAssertGreaterThan(stateStore.nextReportCountdownSeconds, 0)

        stateStore.updateOnlineStatus(false)

        XCTAssertFalse(homeViewModel.isOnline)
        XCTAssertFalse(reportViewModel.isOnline)
    }

    func testRestoreClearsOnlineStateWhenStoredLastReportTimeIsMissing() {
        appStore.location.onlineStatus = true
        appStore.location.lastReportTime = 0

        let stateStore = HomeLocationStateStore(store: appStore)
        stateStore.restoreStateIfNeeded()

        XCTAssertFalse(stateStore.isOnline)
        XCTAssertFalse(appStore.location.onlineStatus)
        XCTAssertEqual(appStore.location.lastReportTime, 0)
        XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
    }

    func testRestoreClearsRuntimeStateWhenPersistedOffline() {
        let stateStore = HomeLocationStateStore(store: appStore)
        stateStore.startLocationReport(at: Int64(Date().timeIntervalSince1970 * 1000))
        appStore.location.onlineStatus = false

        stateStore.restoreStateIfNeeded()

        XCTAssertFalse(stateStore.isOnline)
        XCTAssertEqual(stateStore.nextReportCountdownSeconds, 0)
    }
}

private final class StateObserverOwner {}
