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

import Foundation

/// 列表响应实体，表示后端常见的 total + list 分页或全量列表结构。
struct ListPayload<T: Decodable>: Decodable {
    let total: Int
    let list: [T]

    /// 列表响应的 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case total
        case list
    }

    /// 创建列表响应，主要用于测试和本地兜底数据。
    init(total: Int, list: [T]) {
        self.total = total
        self.list = list
    }

    /// 自定义解码，兼容 total 是字符串或缺失的情况。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        total = try container.decodeLossyInt(forKey: .total) ?? 0
        list = try container.decodeIfPresent([T].self, forKey: .list) ?? []
    }
}

/// 数据列表响应实体，表示后端常见的 total + data 分页结构，并兼容 list 字段。
struct DataListPayload<T: Decodable>: Decodable {
    let total: Int
    let data: [T]

    /// 数据列表响应的 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case total
        case data
        case list
    }

    /// 创建数据列表响应，主要用于测试和本地兜底数据。
    init(total: Int, data: [T]) {
        self.total = total
        self.data = data
    }

    /// 自定义解码，兼容 data/list 字段和 total 字符串。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        total = try container.decodeLossyInt(forKey: .total) ?? 0
        data = try container.decodeIfPresent([T].self, forKey: .data)
            ?? container.decodeIfPresent([T].self, forKey: .list)
            ?? []
    }
}

private extension KeyedDecodingContainer {
    /// 将 Int、Double 或数字字符串宽松解码为整数。
    func decodeLossyInt(forKey key: Key) throws -> Int? {
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
            if let intValue = Int(text) {
                return intValue
            }
            if let doubleValue = Double(text) {
                return Int(doubleValue)
            }
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return Int(value)
        }
        return nil
    }
}
