//
//  AppStoreModuleTests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

/// 验证 AppStore 子模块的持久化、账号隔离与统一清理行为。
final class AppStoreModuleTests: XCTestCase {

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

    override func setUp() {
        super.setUp()
        suiteName = "AppStoreModuleTests.\(UUID().uuidString)"
        defaults = UserDefaults(suiteName: suiteName)
        defaults.removePersistentDomain(forName: suiteName)
        appStore = AppStore(defaults: defaults)
    }

    override func tearDown() {
        defaults.removePersistentDomain(forName: suiteName)
        appStore = nil
        defaults = nil
        suiteName = nil
        super.tearDown()
    }

    func testAccountTypeKnownAndUnknownRawValueRoundTrips() {
        XCTAssertEqual(AppAccountType(rawValue: "scenic_user"), .scenicUser)
        XCTAssertEqual(AppAccountType(rawValue: "store_user"), .storeUser)
        XCTAssertEqual(AppAccountType(rawValue: "future_account"), .unknown("future_account"))
        XCTAssertEqual(AppAccountType.scenicUser.rawValue, "scenic_user")
        XCTAssertEqual(AppAccountType.storeUser.rawValue, "store_user")
        XCTAssertEqual(AppAccountType.unknown("future_account").rawValue, "future_account")
    }

    func testSessionUsesExistingKeysAndPreservesUnknownAccountType() {
        defaults.set("legacy-token", forKey: "key_in_token")
        defaults.set("future_account", forKey: "key_in_account_type")

        XCTAssertEqual(appStore.session.token, "legacy-token")
        XCTAssertEqual(appStore.session.accountType, .unknown("future_account"))

        appStore.session.userId = "1001"
        appStore.session.currentScenicId = 22

        XCTAssertEqual(defaults.string(forKey: "key_in_user_id"), "1001")
        XCTAssertEqual(defaults.string(forKey: "key_in_current_scenic_id"), "22")
        XCTAssertEqual(appStore.session.accountCachePrefix, "1001_future_account")
    }

    func testFeatureStoresAreIsolatedByAccountAndDecodeSnapshots() {
        selectAccount(userId: "1001", type: .scenicUser)
        let permissions = [HomePermissionItem(id: "1", name: "钱包", uri: "wallet")]
        let scenicList = [ScenicInfo(id: 22, name: "测试景区", status: 1)]
        var queueSettings = ScenicQueueSettingsSnapshot()
        queueSettings.shootMinute = 8

        appStore.permissions.savePermissionItems(permissions)
        appStore.permissions.saveRoleScenicList(scenicList)
        appStore.location.onlineStatus = true
        appStore.location.lastReportTime = 123_456
        appStore.location.reminderMinutes = 10
        appStore.payment.isOpenReceiveVoice = true
        appStore.scenicQueue.punchSpotId = "33"
        appStore.scenicQueue.punchSpotName = "东门"
        appStore.scenicQueue.saveSettingsSnapshot(queueSettings)
        appStore.scenicQueue.savePresetVoices([" A ", "", "B"])

        selectAccount(userId: "2002", type: .storeUser)
        XCTAssertTrue(appStore.permissions.permissionItems().isEmpty)
        XCTAssertTrue(appStore.permissions.roleScenicList().isEmpty)
        XCTAssertFalse(appStore.location.onlineStatus)
        XCTAssertEqual(appStore.location.lastReportTime, 0)
        XCTAssertEqual(appStore.location.reminderMinutes, 0)
        XCTAssertFalse(appStore.payment.isOpenReceiveVoice)
        XCTAssertEqual(appStore.scenicQueue.punchSpotId, "")
        XCTAssertNil(appStore.scenicQueue.settingsSnapshot())

        selectAccount(userId: "1001", type: .scenicUser)
        XCTAssertEqual(appStore.permissions.permissionItems(), permissions)
        XCTAssertEqual(appStore.permissions.roleScenicList(), scenicList)
        XCTAssertTrue(appStore.location.onlineStatus)
        XCTAssertEqual(appStore.location.lastReportTime, 123_456)
        XCTAssertEqual(appStore.location.reminderMinutes, 10)
        XCTAssertTrue(appStore.payment.isOpenReceiveVoice)
        XCTAssertTrue(appStore.scenicQueue.hasPunchSpotSaved())
        XCTAssertEqual(appStore.scenicQueue.punchSpotName, "东门")
        XCTAssertEqual(appStore.scenicQueue.settingsSnapshot(), queueSettings)
        XCTAssertEqual(appStore.scenicQueue.presetVoices(), ["A", "B"])
    }

    func testLogoutClearsCurrentAccountModulesAndPreservesLoginPreferences() {
        appStore.session.lastLoginUsername = "13800000000"
        appStore.session.privacyAgreementAccepted = true

        selectAccount(userId: "other", type: .storeUser)
        appStore.scenicQueue.punchSpotId = "99"

        selectAccount(userId: "current", type: .scenicUser)
        appStore.session.token = "token"
        appStore.permissions.legacyRoleId = 41
        appStore.permissions.savePermissionItems([HomePermissionItem(id: "1", name: "钱包", uri: "wallet")])
        appStore.location.onlineStatus = true
        appStore.payment.isOpenReceiveVoice = true
        appStore.scenicQueue.punchSpotId = "33"

        appStore.logout()

        XCTAssertFalse(appStore.session.isLoggedIn)
        XCTAssertEqual(appStore.session.userId, "")
        XCTAssertEqual(appStore.session.lastLoginUsername, "13800000000")
        XCTAssertTrue(appStore.session.privacyAgreementAccepted)

        selectAccount(userId: "current", type: .scenicUser)
        XCTAssertEqual(appStore.permissions.legacyRoleId, 0)
        XCTAssertTrue(appStore.permissions.permissionItems().isEmpty)
        XCTAssertFalse(appStore.location.onlineStatus)
        XCTAssertFalse(appStore.payment.isOpenReceiveVoice)
        XCTAssertEqual(appStore.scenicQueue.punchSpotId, "")

        selectAccount(userId: "other", type: .storeUser)
        XCTAssertEqual(appStore.scenicQueue.punchSpotId, "99")
    }

    private func selectAccount(userId: String, type: AppAccountType) {
        appStore.session.userId = userId
        appStore.session.accountType = type
    }
}
