import Foundation

/// 推送点击后可到达的业务页面。
enum PushDestination: Sendable, Equatable {
    case paymentRecord
    case paymentDetails
    case messageCenter
}

/// 极光/APNs payload 解析结果，仅提取业务消息类型用于点击路由。
struct PushPayload: Sendable, Equatable {
    private let type: String

    /// 从系统通知 userInfo 提取顶层或推送包装层中的业务消息类型。
    nonisolated init(userInfo: [AnyHashable: Any]) {
        type = Self.extractType(from: userInfo)
    }

    /// 从可发送的字符串字典创建 payload，仅保留业务消息类型。
    nonisolated init(values: [String: String]) {
        type = Self.normalizedType(values["type"])
    }

    /// 可发送的规范化字段快照。
    nonisolated var normalizedValues: [String: String] {
        type.isEmpty ? [:] : ["type": type]
    }

    /// 仅根据后端业务消息类型解析目标页面。
    nonisolated var destination: PushDestination {
        switch type {
        case "1":
            return .paymentRecord
        case "6":
            return .paymentDetails
        default:
            return .messageCenter
        }
    }

    private nonisolated static func extractType(
        from dictionary: [AnyHashable: Any],
        depth: Int = 0
    ) -> String {
        guard depth <= 4 else { return "" }
        let directType = normalizedType(dictionary["type"])
        guard directType.isEmpty else { return directType }

        for key in nestedTypeContainerKeys {
            guard let value = dictionary[key] else { continue }
            if let nested = value as? [AnyHashable: Any] {
                let nestedType = extractType(from: nested, depth: depth + 1)
                if !nestedType.isEmpty { return nestedType }
                continue
            }

            guard let text = value as? String,
                  let data = text.data(using: .utf8),
                  let object = try? JSONSerialization.jsonObject(with: data),
                  let nested = object as? [String: Any]
            else { continue }

            let bridged = Dictionary(uniqueKeysWithValues: nested.map {
                (AnyHashable($0.key), $0.value)
            })
            let nestedType = extractType(from: bridged, depth: depth + 1)
            if !nestedType.isEmpty { return nestedType }
        }
        return ""
    }

    private nonisolated static func normalizedType(_ value: Any?) -> String {
        switch value {
        case let string as String:
            return string.trimmingCharacters(in: .whitespacesAndNewlines)
        case let number as NSNumber:
            return number.stringValue
        default:
            return ""
        }
    }

    private nonisolated static let nestedTypeContainerKeys = [
        "extras", "extra", "JMessageExtra", "n_extras",
    ]
}
