//
//  HomeCommonMenuStoreTests.swift
//  suixinkanTests
//
//  Created by Codex on 2026/6/22.
//

import XCTest
@testable import suixinkan

/// 首页常用应用存储测试，覆盖默认值、过滤和别名去重。
final class HomeCommonMenuStoreTests: XCTestCase {
    /// 测试首次无配置时会按顶层权限生成默认常用应用。
    func testLoadCreatesDefaultCommonMenusFromTopLevelPermissions() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("space_settings"),
            menu("wallet"),
            menu("cloud_management"),
            menu("message_center")
        ]

        let uris = store.load(
            menuItems: menus,
            roleCode: "photographer",
            topLevelPermissionURIs: ["space_settings", "wallet", "cloud_management", "message_center"]
        )

        XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "message_center"])
        XCTAssertEqual(
            defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"),
            ["space_settings", "wallet", "cloud_management", "message_center"]
        )
    }

    /// 测试顶层权限超过 4 个时只取前 4 个默认常用应用。
    func testDefaultCommonURIsTakeFirstFourWhenMoreThanFourPermissions() {
        let availableURIs: Set<String> = [
            "space_settings",
            "wallet",
            "cloud_management",
            "message_center",
            "task_management"
        ]
        let uris = HomeCommonMenuStore.defaultCommonURIs(
            orderedTopLevelURIs: [
                "space_settings",
                "wallet",
                "cloud_management",
                "message_center",
                "task_management"
            ],
            availableURIs: availableURIs
        )

        XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "message_center"])
    }

    /// 测试角色没有旧硬编码默认 URI 时仍能从权限列表生成常用应用。
    func testLoadCreatesDefaultsWithoutLegacyPreferredURIs() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("space_settings"),
            menu("wallet"),
            menu("cloud_management")
        ]

        let uris = store.load(
            menuItems: menus,
            roleCode: "editor",
            topLevelPermissionURIs: ["space_settings", "wallet", "cloud_management"]
        )

        XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management"])
    }

    /// 测试已保存 URI 会按当前权限和 Android 白名单过滤并解析同义 URI。
    func testLoadFiltersSavedUrisByCurrentPermissions() {
        let defaults = makeIsolatedDefaults()
        defaults.set(["task_management", "unknown", "pm"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("task_management_editor"),
            menu("project_edit")
        ]

        let uris = store.load(
            menuItems: menus,
            roleCode: "photographer",
            topLevelPermissionURIs: ["task_management_editor", "project_edit"]
        )

        XCTAssertEqual(uris, ["task_management_editor"])
    }

    /// 测试同一角色不同账号使用独立的常用应用缓存。
    func testLoadUsesAccountScopedStorageKeys() {
        let defaults = makeIsolatedDefaults()
        defaults.set(
            ["wallet"],
            forKey: HomeCommonMenuStore.storageKey(roleCode: "photographer", accountScope: "scenic_user_101")
        )
        defaults.set(
            ["cloud_management"],
            forKey: HomeCommonMenuStore.storageKey(roleCode: "photographer", accountScope: "store_user_101")
        )
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("wallet"),
            menu("cloud_management")
        ]

        let scenic = store.load(
            menuItems: menus,
            roleCode: "photographer",
            accountScope: "scenic_user_101",
            topLevelPermissionURIs: ["wallet", "cloud_management"]
        )
        let storeAccount = store.load(
            menuItems: menus,
            roleCode: "photographer",
            accountScope: "store_user_101",
            topLevelPermissionURIs: ["wallet", "cloud_management"]
        )

        XCTAssertEqual(scenic, ["wallet"])
        XCTAssertEqual(storeAccount, ["cloud_management"])
    }

    /// 测试不同角色使用独立存储 key。
    func testLoadUsesRoleScopedStorageKeys() {
        let defaults = makeIsolatedDefaults()
        defaults.set(["wallet"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
        defaults.set(["cloud_management"], forKey: HomeCommonMenuStore.storageKeyPrefix + "editor")
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("wallet"),
            menu("cloud_management")
        ]

        let roleOne = store.load(
            menuItems: menus,
            roleCode: "photographer",
            topLevelPermissionURIs: ["wallet", "cloud_management"]
        )
        let roleTwo = store.load(
            menuItems: menus,
            roleCode: "editor",
            topLevelPermissionURIs: ["wallet", "cloud_management"]
        )

        XCTAssertEqual(roleOne, ["wallet"])
        XCTAssertEqual(roleTwo, ["cloud_management"])
    }

    /// 测试添加常用应用时会按同义 URI 去重。
    func testAddDeduplicatesAliases() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("task_management_editor")
        ]

        let uris = store.add(
            "task_management",
            current: ["task_management_editor"],
            menuItems: menus,
            roleCode: "photographer"
        )

        XCTAssertEqual(uris, ["task_management_editor"])
    }

    /// 测试移除常用应用时会移除同义 URI。
    func testRemoveDeletesAliases() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)

        let uris = store.remove("pm", current: ["project_edit", "pm_manager", "location_report"], roleCode: "photographer")

        XCTAssertEqual(uris, ["pm_manager", "location_report"])
    }

    /// 测试无 role_code 时不读写常用应用。
    func testLoadReturnsEmptyWhenRoleCodeIsMissing() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)

        let uris = store.load(
            menuItems: [menu("wallet")],
            roleCode: nil,
            topLevelPermissionURIs: ["wallet"]
        )

        XCTAssertTrue(uris.isEmpty)
        XCTAssertNil(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"))
    }

    /// 测试从 legacy role id key 一次性迁移常用菜单。
    func testLoadMigratesLegacyRoleIdStorageKey() {
        let defaults = makeIsolatedDefaults()
        defaults.set(["wallet", "cloud_management"], forKey: HomeCommonMenuStore.storageKeyPrefix + "46")
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [menu("wallet"), menu("cloud_management")]

        let uris = store.load(
            menuItems: menus,
            roleCode: "store_admin",
            legacyRoleId: 46,
            topLevelPermissionURIs: ["wallet", "cloud_management"]
        )

        XCTAssertEqual(uris, ["wallet", "cloud_management"])
        XCTAssertEqual(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "store_admin"), ["wallet", "cloud_management"])
        XCTAssertNil(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "46"))
    }

    /// 测试旧 roleCode key 会迁移到账号作用域 key。
    func testLoadMigratesLegacyRoleCodeStorageKeyToAccountScopedKey() {
        let defaults = makeIsolatedDefaults()
        defaults.set(["wallet", "cloud_management"], forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer")
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [menu("wallet"), menu("cloud_management")]

        let uris = store.load(
            menuItems: menus,
            roleCode: "photographer",
            accountScope: "scenic_user_101",
            topLevelPermissionURIs: ["wallet", "cloud_management"]
        )

        XCTAssertEqual(uris, ["wallet", "cloud_management"])
        XCTAssertEqual(
            defaults.stringArray(forKey: HomeCommonMenuStore.storageKey(roleCode: "photographer", accountScope: "scenic_user_101")),
            ["wallet", "cloud_management"]
        )
        XCTAssertNil(defaults.stringArray(forKey: HomeCommonMenuStore.storageKeyPrefix + "photographer"))
    }

    /// 测试 Android 白名单外的 URI 不会进入默认常用应用。
    func testDefaultCommonURIsExcludeMenusMissingFromAndroidCatalog() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("wallet"),
            menu("album_list"),
            menu("cloud_storage_transit"),
            menu("message_center")
        ]

        let uris = store.load(
            menuItems: menus,
            roleCode: "photographer",
            accountScope: "scenic_user_101",
            topLevelPermissionURIs: ["wallet", "album_list", "cloud_storage_transit", "message_center"]
        )

        XCTAssertEqual(uris, ["wallet", "message_center"])
    }

    /// 测试已保存常用应用超过 4 个时只过滤权限，不会被强制截断。
    func testSavedCommonURIsAreNotTruncatedToFour() {
        let defaults = makeIsolatedDefaults()
        defaults.set(
            ["space_settings", "wallet", "cloud_management", "asset_management", "message_center"],
            forKey: HomeCommonMenuStore.storageKey(roleCode: "photographer", accountScope: "scenic_user_101")
        )
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("space_settings"),
            menu("wallet"),
            menu("cloud_management"),
            menu("asset_management"),
            menu("message_center")
        ]

        let uris = store.load(
            menuItems: menus,
            roleCode: "photographer",
            accountScope: "scenic_user_101",
            topLevelPermissionURIs: menus.map(\.uri)
        )

        XCTAssertEqual(uris, ["space_settings", "wallet", "cloud_management", "asset_management", "message_center"])
    }

    /// 测试默认常用只取顶层权限，不会用子权限补位。
    func testDefaultCommonURIsUseOnlyTopLevelPermissions() {
        let defaults = makeIsolatedDefaults()
        let store = HomeCommonMenuStore(defaults: defaults)
        let menus = [
            menu("task_management"),
            menu("message_center")
        ]

        let uris = store.load(
            menuItems: menus,
            roleCode: "photographer",
            accountScope: "scenic_user_101",
            topLevelPermissionURIs: ["task_management"]
        )

        XCTAssertEqual(uris, ["task_management"])
    }

    /// 创建测试菜单实体。
    private func menu(_ uri: String) -> HomeMenuItem {
        HomeMenuItem(title: HomeMenuRouter.title(for: uri), uri: uri, iconSrc: nil)
    }

    /// 创建独立 UserDefaults，避免测试污染真实 App 偏好。
    private func makeIsolatedDefaults() -> UserDefaults {
        let suiteName = "suixinkan.home.tests.\(UUID().uuidString)"
        let defaults = UserDefaults(suiteName: suiteName)!
        defaults.removePersistentDomain(forName: suiteName)
        return defaults
    }
}
