//
//  PushPayload.swift
//  suixinkan
//
//  Created by Codex on 2026/6/26.
//

import Foundation

/// APNs token 工具，把系统返回的 Data 转成后端可接收的小写十六进制字符串。
enum APNsDeviceToken {
    static func hexString(from data: Data) -> String {
        data.map { String(format: "%02x", $0) }.joined()
    }
}

/// 推送 payload 解析器，兼容顶层字段和第三方通道常见 extras/data 嵌套结构。
struct PushPayload: Sendable {
    enum Route: Sendable, Equatable {
        case payment
        case order
        case verificationOrder
        case task
        case queue
        case messageCenter
    }

    private let values: [String: String]

    nonisolated init(userInfo: [AnyHashable: Any]) {
        var result: [String: String] = [:]
        for (key, value) in userInfo {
            guard let key = key as? String else { continue }
            result[key] = Self.stringValue(value)
            if key == "extras" || key == "extra" || key == "data" || key == "JMessageExtra" {
                Self.mergeJSON(value, into: &result)
            }
        }
        values = result
    }

    nonisolated var route: Route {
        let typeText = values["type"] ?? ""
        let routeText = values["route"] ?? ""
        let uriText = values["uri"] ?? ""
        let actionText = values["action"] ?? ""
        let merged = [typeText, routeText, uriText, actionText].joined(separator: " ").lowercased()

        if typeText == "1" || merged.contains("payment") || merged.contains("pay") || merged.contains("收款") {
            return .payment
        }
        if merged.contains("queue") || merged.contains("排队") || merged.contains("叫号") || uriText == "/scenic-queue" {
            return .queue
        }
        if merged.contains("verification") || merged.contains("writeoff") || merged.contains("核销") {
            return .verificationOrder
        }
        if merged.contains("order") || merged.contains("订单") {
            return .order
        }
        if merged.contains("task") || merged.contains("任务") {
            return .task
        }
        return .messageCenter
    }

    nonisolated private static func mergeJSON(_ value: Any, into result: inout [String: String]) {
        if let dict = value as? [String: Any] {
            for (key, value) in dict {
                result[key] = stringValue(value)
                mergeJSON(value, into: &result)
            }
            return
        }

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

        for (key, value) in object {
            result[key] = stringValue(value)
            mergeJSON(value, into: &result)
        }
    }

    nonisolated private static func stringValue(_ value: Any?) -> String {
        switch value {
        case let string as String:
            return string
        case let number as NSNumber:
            return number.stringValue
        case .some(let value):
            return "\(value)"
        case nil:
            return ""
        }
    }
}
