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

import Foundation

/// 阿里云 OSS STS 配置响应实体，表示一次临时上传授权。
struct AliyunOSSResponse: Decodable, Equatable {
    let baseUrl: String
    let endpoint: String
    let region: String
    let bucket: String
    let expireSeconds: Int
    let credentials: AliyunOSSCredentials

    /// 阿里云 OSS STS 配置响应 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case baseUrl = "base_url"
        case endpoint
        case region
        case bucket
        case expireSeconds = "expire_seconds"
        case credentials
    }

    /// 自定义解码，兼容后端字段类型不稳定的情况。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        baseUrl = try container.decodeLossyString(forKey: .baseUrl)
        endpoint = try container.decodeLossyString(forKey: .endpoint)
        region = try container.decodeLossyString(forKey: .region)
        bucket = try container.decodeLossyString(forKey: .bucket)
        expireSeconds = try container.decodeLossyInt(forKey: .expireSeconds) ?? 0
        credentials = try container.decode(AliyunOSSCredentials.self, forKey: .credentials)
    }
}

/// 阿里云 OSS 临时凭证实体，表示 SDK 上传所需的访问密钥和安全 token。
struct AliyunOSSCredentials: Decodable, Equatable {
    let accessKeyId: String
    let accessKeySecret: String
    let securityToken: String

    /// 阿里云 OSS 临时凭证 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case accessKeyId = "access_key_id"
        case accessKeySecret = "access_key_secret"
        case securityToken = "security_token"
    }

    /// 自定义解码，兼容后端字段类型不稳定的情况。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        accessKeyId = try container.decodeLossyString(forKey: .accessKeyId)
        accessKeySecret = try container.decodeLossyString(forKey: .accessKeySecret)
        securityToken = try container.decodeLossyString(forKey: .securityToken)
    }
}

private extension KeyedDecodingContainer {
    /// 将 String、数字和 Bool 宽松解码为字符串。
    func decodeLossyString(forKey key: Key) throws -> String {
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return String(value)
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return String(value)
        }
        if let value = try? decodeIfPresent(Bool.self, forKey: key) {
            return value ? "true" : "false"
        }
        return ""
    }

    /// 将 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
    }
}
