//
//  HomeCommonMenuStore.swift
//  suixinkan
//
//  Created by Codex on 2026/6/22.
//

import Foundation

/// 首页常用应用存储服务，负责按当前角色权限过滤和持久化常用 URI。
struct HomeCommonMenuStore {
    static let storageKeyPrefix = "home.common.menu.uris.role."
    static let accountScopedStorageKeyPrefix = "home.common.menu.uris.account."

    /// 与 Android `Constants.menuList` 对齐的首页菜单 URI 白名单。
    static let androidHomeMenuURIs: Set<String> = [
        "space_settings",
        "wallet",
        "cloud_management",
        "asset_management",
        "task_management",
        "schedule_management",
        "system_settings",
        "message_center",
        "checkin_points",
        "sample_management",
        "live_stream_management",
        "verification_order",
        "live_album",
        "travel_album",
        "pm",
        "location_report",
        "report_photographer",
        "promotion_page",
        "registration_invitation",
        "store",
        "fly",
        "pilot_cert",
        "task_management_editor",
        "pm_manager",
        "pilot_controller",
        "/scenic-queue",
        "operating-area",
        "/scenic-order-manage",
        "cooperation_order"
    ]

    private let defaults: UserDefaults

    /// 初始化常用应用存储服务，并允许测试注入独立 UserDefaults。
    init(defaults: UserDefaults = .standard) {
        self.defaults = defaults
    }

    /// 按 Android 规则生成默认常用 URI：先取顶层前 4 个 URI，再与 menuList 白名单求交。
    static func defaultCommonURIs(orderedTopLevelURIs: [String]) -> [String] {
        let rawTopLevel = orderedTopLevelURIs.compactMap { uri -> String? in
            let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
            return trimmed.isEmpty ? nil : trimmed
        }
        let candidates = rawTopLevel.count > 4 ? Array(rawTopLevel.prefix(4)) : rawTopLevel
        return candidates.filter { isAndroidHomeMenuURI($0) }
    }

    /// 返回顶层权限中属于 Android menuList 的 URI，顺序与 API 一致。
    static func availableTopLevelMenuURIs(from orderedTopLevelURIs: [String]) -> [String] {
        orderedTopLevelURIs.compactMap { uri -> String? in
            let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
            guard !trimmed.isEmpty, isAndroidHomeMenuURI(trimmed) else { return nil }
            return trimmed
        }
    }

    /// 读取常用 URI；无角色时返回空，有 saved 时精确匹配且不回退默认。
    func load(
        menuItems: [HomeMenuItem],
        roleCode: String?,
        accountScope: String? = nil,
        legacyRoleId: Int? = nil,
        topLevelPermissionURIs: [String]
    ) -> [String] {
        guard let roleCode, !roleCode.isEmpty else { return [] }
        migrateLegacyStorageIfNeeded(roleCode: roleCode, accountScope: accountScope, legacyRoleId: legacyRoleId)

        let rawTopLevel = topLevelPermissionURIs.compactMap { uri -> String? in
            let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
            return trimmed.isEmpty ? nil : trimmed
        }
        let availableTopLevel = Self.availableTopLevelMenuURIs(from: rawTopLevel)
        let availableTopLevelSet = Set(availableTopLevel)
        let key = Self.storageKey(roleCode: roleCode, accountScope: accountScope)
        let saved = defaults.stringArray(forKey: key) ?? []
        let defaultCommon = Self.defaultCommonURIs(orderedTopLevelURIs: rawTopLevel)

        HomeCommonMenuDiagnostics.log(
            step: "context",
            fields: [
                "roleCode": roleCode,
                "accountScope": accountScope ?? "",
                "storageKey": key
            ]
        )
        HomeCommonMenuDiagnostics.log(
            step: "rawTopLevel",
            fields: [
                "count": String(rawTopLevel.count),
                "uris": HomeCommonMenuDiagnostics.formatURIList(rawTopLevel)
            ]
        )
        HomeCommonMenuDiagnostics.log(
            step: "availableFunctions",
            fields: [
                "count": String(availableTopLevel.count),
                "uris": HomeCommonMenuDiagnostics.formatURIList(availableTopLevel)
            ]
        )
        HomeCommonMenuDiagnostics.log(
            step: "savedCommon",
            fields: [
                "uris": HomeCommonMenuDiagnostics.formatURIList(saved)
            ]
        )
        HomeCommonMenuDiagnostics.log(
            step: "defaultCommon",
            fields: [
                "uris": HomeCommonMenuDiagnostics.formatURIList(defaultCommon)
            ]
        )

        let finalCommon: [String]
        if !saved.isEmpty {
            finalCommon = saved.filter { availableTopLevelSet.contains($0) }
        } else {
            finalCommon = defaultCommon
            save(finalCommon, roleCode: roleCode, accountScope: accountScope)
        }

        HomeCommonMenuDiagnostics.log(
            step: "finalCommon",
            fields: [
                "count": String(finalCommon.count),
                "uris": HomeCommonMenuDiagnostics.formatURIList(finalCommon)
            ]
        )
        _ = menuItems
        return finalCommon
    }

    /// 将指定 URI 加入常用应用，使用精确 URI 匹配。
    func add(
        _ uri: String,
        current: [String],
        topLevelPermissionURIs: [String],
        roleCode: String?,
        accountScope: String? = nil
    ) -> [String] {
        guard let roleCode, !roleCode.isEmpty else { return current }
        let availableTopLevel = Set(Self.availableTopLevelMenuURIs(from: topLevelPermissionURIs))
        let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
        guard availableTopLevel.contains(trimmed), !current.contains(trimmed) else { return current }
        let next = current + [trimmed]
        save(next, roleCode: roleCode, accountScope: accountScope)
        return next
    }

    /// 从常用应用中移除指定 URI，使用精确 URI 匹配。
    func remove(_ uri: String, current: [String], roleCode: String?, accountScope: String? = nil) -> [String] {
        guard let roleCode, !roleCode.isEmpty else { return current }
        let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
        let next = current.filter { $0 != trimmed }
        save(next, roleCode: roleCode, accountScope: accountScope)
        return next
    }

    /// 保存指定角色的常用 URI。
    func save(_ uris: [String], roleCode: String, accountScope: String? = nil) {
        defaults.set(uris, forKey: Self.storageKey(roleCode: roleCode, accountScope: accountScope))
    }

    /// 若账号级 key 无数据，则从旧 roleCode 或 legacy role id key 一次性迁移常用菜单。
    func migrateLegacyStorageIfNeeded(roleCode: String, accountScope: String? = nil, legacyRoleId: Int?) {
        let newKey = Self.storageKey(roleCode: roleCode, accountScope: accountScope)
        guard defaults.stringArray(forKey: newKey) == nil else { return }

        let legacyKeys = [
            legacyStorageKey(for: roleCode),
            legacyRoleId.map { legacyStorageKey(for: $0) }
        ].compactMap { $0 }

        for legacyKey in legacyKeys {
            guard let legacyData = defaults.stringArray(forKey: legacyKey), !legacyData.isEmpty else { continue }
            defaults.set(legacyData, forKey: newKey)
            defaults.removeObject(forKey: legacyKey)
            return
        }
    }

    /// 生成按账号和 role_code 隔离的 UserDefaults key。
    static func storageKey(roleCode: String, accountScope: String?) -> String {
        let normalizedScope = accountScope?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        if normalizedScope.isEmpty {
            return storageKeyPrefix + roleCode
        }
        return accountScopedStorageKeyPrefix + normalizedScope + ".role." + roleCode
    }

    /// 旧版按 numeric role id 存储的 key。
    private func legacyStorageKey(for roleId: Int) -> String {
        Self.storageKeyPrefix + String(roleId)
    }

    /// 旧版按 role_code 存储的 key。
    private func legacyStorageKey(for roleCode: String) -> String {
        Self.storageKeyPrefix + roleCode
    }

    /// 判断 URI 是否属于 Android 首页菜单白名单。
    private static func isAndroidHomeMenuURI(_ uri: String) -> Bool {
        androidHomeMenuURIs.contains(uri)
    }
}
