//
//  AppStoreCacheMigrationTests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

/// 验证覆盖升级清理、强制退出以及缓存结构版本幂等性。
final class AppStoreCacheMigrationTests: XCTestCase {

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

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

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

    func testFirstInitializationClearsLegacyAndPreReleaseKeysAndForcesLogout() {
        let exactKeysToRemove = [
            "suixinkan.session.v1",
            "apns_device_token",
            "apns_uploaded_token",
            "home.common.menu.uris",
            "home.common.menu.android.baseline.v2",
            "home.routing.unknown.records",
            "payment.voice.broadcast.enabled",
            "key_in_token",
            "key_last_login_username",
            "key_privacy_agreement_accepted",
            "key_in_user_id",
            "key_in_user_name",
            "key_in_real_name",
            "key_in_avatar",
            "key_in_phone",
            "key_in_account_type",
            "key_in_account_display_name",
            "key_in_role_id",
            "key_in_role_code",
            "key_in_role_name",
            "key_in_current_scenic_id",
            "key_in_current_scenic_name",
            "key_in_current_store_id",
            "key_role_permission_list",
            "key_in_permission",
            "key_current_role_scenic_list",
            "key_online_status",
            "key_last_location_report_time",
            "key_location_reminder_minutes",
            "key_is_open_receive_voice",
            "scenic_queue_tts_enabled",
            "scenic_queue_background_poll_enabled",
            "scenic_queue_selected_spot_id",
            "scenic_queue_selected_spot_name",
            "scenic_queue_custom_tts_text",
            "scenic_queue_photo_estimate_seconds",
            "scenic_queue_broadcast_interval_seconds",
            "scenic_queue_countdown_threshold_seconds",
            "scenic_queue_show_start_shooting_button",
            "scenic_queue_auto_call_ahead_count",
            "scenic_queue_quick_call_button_enabled",
            "scenic_queue_prepare_call_button_enabled",
            "scenic_queue_config_logs",
            "scenic_queue_settings_snapshot",
            "scenic_queue_preset_voices",
        ]
        let dynamicKeysToRemove = [
            "account_store_user_1001_31_22_scenic_22_scenic_queue_selected_spot_id",
            "account_store_user_1001_31_22_scenic_22_scenic_queue_selected_spot_name",
            "account_store_user_1001_31_22_scenic_22_scenic_queue_custom_tts_text_spot_33",
            "account_store_user_1001_31_22_scenic_22_scenic_queue_settings_snapshot_spot_33",
            "account_store_user_1001_31_22_scenic_22_scenic_queue_preset_voices_spot_33",
            "scenic_22_spot_33_scenic_queue_settings_snapshot",
            "scenic_22_spot_33_scenic_queue_preset_voices",
            "scenic_22_scenic_queue_settings_snapshot",
            "1001_store_user_key_in_role_id",
            "1001_store_user_key_role_permission_list",
            "1001_store_user_key_in_permission",
            "1001_store_user_key_current_role_scenic_list",
            "1001_store_user_key_online_status",
            "1001_store_user_key_last_location_report_time",
            "1001_store_user_key_location_reminder_minutes",
            "1001_store_user_key_is_open_receive_voice",
            "1001_store_user_role__common_uris",
            "1001_store_user_role_photographer_common_uris",
            "1001_store_user__scenic_queue_punch_spot_id",
            "1001_store_user__scenic_queue_punch_spot_name",
            "1001_store_user__scenic_queue_punch_spot_remark",
            "1001_store_user__scenic_queue_remark",
            "1001_store_user__scenic_queue_settings_snapshot",
            "1001_store_user__scenic_queue_offline_tts_v1",
            "1001_store_user__scenic_queue_preset_voices_v1",
        ]
        let keysToPreserve = [
            "third_party.sentinel",
            "home.common.menu.uris.extra",
            "account_store_user_1001_31_22_scenic_22_scenic_queue_selected_spot_identifier",
            "account_store_user_1001_31_22_scenic_22_scenic_queue_custom_tts_text_spot_33_backup",
            "scenic_22_spot_33_scenic_queue_settings_snapshot_backup",
            "unrelated_key_in_permission_extra",
            "scenic_user_1001_key_in_role_code",
            "scenic_user_1001_scenic_22_scenic_queue_punch_spot_id",
            "scenic_user_1001_scenic_22_spot_33_scenic_queue_settings_snapshot",
        ]
        let keysToRemove = exactKeysToRemove + dynamicKeysToRemove
        keysToRemove.forEach { defaults.set("legacy", forKey: $0) }
        keysToPreserve.forEach { defaults.set("keep", forKey: $0) }
        defaults.set(true, forKey: "key_privacy_agreement_accepted")

        let store = AppStore(defaults: defaults)

        XCTAssertFalse(store.session.isLoggedIn)
        XCTAssertNil(store.session.lastLoginUsername)
        XCTAssertFalse(store.session.privacyAgreementAccepted)
        keysToRemove.forEach { XCTAssertNil(defaults.object(forKey: $0), "未清理 Key：\($0)") }
        keysToPreserve.forEach {
            XCTAssertEqual(defaults.string(forKey: $0), "keep", "误清理 Key：\($0)")
        }
        XCTAssertEqual(
            defaults.integer(forKey: AppStoreCacheMigrator.schemaVersionKey),
            AppStoreCacheMigrator.currentSchemaVersion
        )
    }

    func testMigrationRunsOnlyOnceAndPreservesNewSession() {
        defaults.set("keep", forKey: "third_party.sentinel")
        var store = AppStore(defaults: defaults)
        store.session.token = "new-token"
        store.session.lastLoginUsername = "13800000000"
        store.session.privacyAgreementAccepted = true
        store.session.userId = "1001"
        store.session.accountType = .scenicUser
        store.session.roleCode = "photographer"
        store.session.currentScenicId = 22
        store.scenicQueue.punchSpotId = "33"
        store.scenicQueue.punchSpotName = "东门"

        store = AppStore(defaults: defaults)

        XCTAssertTrue(store.session.isLoggedIn)
        XCTAssertEqual(store.session.token, "new-token")
        XCTAssertEqual(store.session.lastLoginUsername, "13800000000")
        XCTAssertTrue(store.session.privacyAgreementAccepted)
        XCTAssertEqual(store.session.roleCode, "photographer")
        XCTAssertEqual(store.session.currentScenicId, 22)
        XCTAssertEqual(store.scenicQueue.punchSpotId, "33")
        XCTAssertEqual(store.scenicQueue.punchSpotName, "东门")
        XCTAssertEqual(defaults.string(forKey: "third_party.sentinel"), "keep")
    }
}
