//
//  ProfileModels.swift
//  suixinkan
//
//  Created by Codex on 2026/6/20.
//

import Foundation

/// 用户资料响应实体，表示“我的”页面展示的账号基础信息。
struct UserInfoResponse: Decodable, Equatable {
    let avatar: String
    let realName: String
    let phone: String
    let nickname: String
    let roleName: String
    let status: Int
    let statusName: String

    /// 用户资料响应的 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case avatar
        case realName = "real_name"
        case phone
        case nickname
        case roleName = "role_name"
        case status
        case statusName = "status_name"
    }

    /// 创建用户资料实体，主要用于本地更新和预览默认值。
    init(
        avatar: String = "",
        realName: String = "",
        phone: String = "",
        nickname: String = "",
        roleName: String = "",
        status: Int = 0,
        statusName: String = ""
    ) {
        self.avatar = avatar
        self.realName = realName
        self.phone = phone
        self.nickname = nickname
        self.roleName = roleName
        self.status = status
        self.statusName = statusName
    }

    /// 自定义解码，兼容后端字段类型不稳定的情况。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        avatar = try container.decodeLossyString(forKey: .avatar)
        realName = try container.decodeLossyString(forKey: .realName)
        phone = try container.decodeLossyString(forKey: .phone)
        nickname = try container.decodeLossyString(forKey: .nickname)
        roleName = try container.decodeLossyString(forKey: .roleName)
        status = try container.decodeLossyInt(forKey: .status) ?? 0
        statusName = try container.decodeLossyString(forKey: .statusName)
    }
}

/// 用户资料更新请求实体，表示昵称、密码和头像修改参数。
struct UpdateInfoRequest: Encodable {
    let nickname: String?
    let password: String?
    let avatar: String?
}

/// 实名认证响应实体，包裹当前用户的认证详情。
struct RealNameInfoResponse: Decodable, Equatable {
    let realNameInfo: RealNameInfo?

    /// 实名认证响应的 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case realNameInfo = "real_name_info"
    }
}

/// 实名认证信息实体，表示当前用户实名审核状态和失败原因。
struct RealNameInfo: Decodable, Equatable {
    let realName: String
    let idCardNo: String
    let auditStatus: Int
    let auditStatusText: String?
    let rejectReason: String?
    let startDate: String?
    let endDate: String?
    let isLongValid: Bool
    let frontUrl: String?
    let backUrl: String?
    let auditorId: Int?
    let auditor: RealNameAuditor?
    let auditAt: String?

    /// 当前认证是否已审核通过。
    var verified: Bool {
        auditStatus == 2
    }

    /// 实名认证信息的 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case realName = "real_name"
        case idCardNo = "id_card_no"
        case auditStatus = "audit_status"
        case auditStatusText = "audit_status_text"
        case rejectReason = "reject_reason"
        case startDate = "start_date"
        case endDate = "end_date"
        case isLongValid = "is_long_valid"
        case frontUrl = "front_url"
        case backUrl = "back_url"
        case auditorId = "auditor_id"
        case auditor
        case auditAt = "audit_at"
    }

    /// 自定义解码，兼容审核状态字段类型不稳定的情况。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        realName = try container.decodeLossyString(forKey: .realName)
        idCardNo = try container.decodeLossyString(forKey: .idCardNo)
        auditStatus = try container.decodeLossyInt(forKey: .auditStatus) ?? 0
        auditStatusText = try container.decodeIfPresent(String.self, forKey: .auditStatusText)
        rejectReason = try container.decodeIfPresent(String.self, forKey: .rejectReason)
        startDate = try container.decodeIfPresent(String.self, forKey: .startDate)
        endDate = try container.decodeIfPresent(String.self, forKey: .endDate)
        isLongValid = (try container.decodeLossyInt(forKey: .isLongValid) ?? 0) == 1
        frontUrl = try container.decodeIfPresent(String.self, forKey: .frontUrl)
        backUrl = try container.decodeIfPresent(String.self, forKey: .backUrl)
        auditorId = try container.decodeLossyInt(forKey: .auditorId)
        auditor = try container.decodeIfPresent(RealNameAuditor.self, forKey: .auditor)
        auditAt = try container.decodeIfPresent(String.self, forKey: .auditAt)
    }
}

/// 实名认证审核人实体，表示后台审核人的基础展示信息。
struct RealNameAuditor: Decodable, Equatable {
    let id: Int
    let name: String

    /// 审核人 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case id
        case name
    }

    /// 自定义解码，兼容审核人 ID 类型不稳定。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decodeLossyInt(forKey: .id) ?? 0
        name = try container.decodeLossyString(forKey: .name)
    }
}

/// 实名认证提交请求实体，表示用户填写的姓名、证件号、短信和证件图片。
struct RealNameAuthRequest: Encodable, Equatable {
    let realName: String
    let idCardNo: String
    let smsVerifyCode: String
    let startDate: String
    let endDate: String
    let isLongValid: Int
    let frontUrl: String
    let backUrl: String

    /// 实名认证提交请求 JSON 字段映射。
    enum CodingKeys: String, CodingKey {
        case realName = "real_name"
        case idCardNo = "id_card_no"
        case smsVerifyCode = "sms_verify_code"
        case startDate = "start_date"
        case endDate = "end_date"
        case isLongValid = "is_long_valid"
        case frontUrl = "front_url"
        case backUrl = "back_url"
    }
}

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