//
//  InviteModels.swift
//  suixinkan
//
//  Created by Codex on 2026/6/24.
//

import Foundation

/// 邀请信息响应实体，表示邀请码、邀请链接和规则文案。
struct InviteInfoResponse: Decodable, Equatable {
    let enableInvite: Bool
    let inviteCode: String
    let inviteUrl: String
    let description: [String]

    /// 字段映射，兼容后端下划线命名。
    enum CodingKeys: String, CodingKey {
        case enableInvite = "enable_invite"
        case inviteCode = "invite_code"
        case inviteUrl = "invite_url"
        case description
    }

    /// 宽松解码邀请信息。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        enableInvite = try container.decodeInviteLossyBool(forKey: .enableInvite) ?? true
        inviteCode = try container.decodeInviteLossyString(forKey: .inviteCode)
        inviteUrl = try container.decodeInviteLossyString(forKey: .inviteUrl)
        description = (try? container.decodeIfPresent([String].self, forKey: .description)) ?? []
    }
}

/// 邀请用户实体，表示邀请记录里的摄影师。
struct InviteUserItem: Decodable, Identifiable, Hashable {
    let id: Int
    let realName: String
    let phone: String
    let avatar: String
    let createdAt: String
    let inviteLevel: Int

    /// 字段映射，兼容后端下划线命名。
    enum CodingKeys: String, CodingKey {
        case id
        case realName = "real_name"
        case phone
        case avatar
        case createdAt = "created_at"
        case inviteLevel = "invite_level"
    }

    /// 宽松解码邀请用户字段。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decodeInviteLossyInt(forKey: .id) ?? 0
        realName = try container.decodeInviteLossyString(forKey: .realName)
        phone = try container.decodeInviteLossyString(forKey: .phone)
        avatar = try container.decodeInviteLossyString(forKey: .avatar)
        createdAt = try container.decodeInviteLossyString(forKey: .createdAt)
        inviteLevel = try container.decodeInviteLossyInt(forKey: .inviteLevel) ?? 0
    }
}

/// 邀请记录页面展示行实体，统一邀请用户和奖励明细的展示字段。
struct InviteDisplayRow: Identifiable, Equatable {
    let id: String
    let title: String
    let subtitle: String
    let amount: String
    let time: String
    let phone: String
    let avatar: String
    let inviteLevel: Int

    /// 邀请层级文案。
    var levelText: String {
        inviteLevel == 1 ? "一级" : "二级"
    }

    /// 头像占位文案。
    var avatarPlaceholder: String {
        if let first = title.first {
            return String(first)
        }
        if let first = phone.first {
            return String(first)
        }
        return "?"
    }
}

/// 邀请记录分段类型。
enum InviteRecordTab: CaseIterable, Equatable {
    case invite
    case reward

    /// 分段标题。
    var title: String {
        switch self {
        case .invite: return "邀请记录"
        case .reward: return "奖励记录"
        }
    }
}

private extension KeyedDecodingContainer {
    /// 将 String、数字和 Bool 宽松解码为字符串。
    func decodeInviteLossyString(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 ? "1" : "0"
        }
        return ""
    }

    /// 将 String、Double 和 Int 宽松解码为 Int。
    func decodeInviteLossyInt(forKey key: Key) throws -> Int? {
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return Int(value)
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
            return Int(text) ?? Double(text).map(Int.init)
        }
        return nil
    }

    /// 将 String、数字和 Bool 宽松解码为 Bool。
    func decodeInviteLossyBool(forKey key: Key) throws -> Bool? {
        if let value = try? decodeIfPresent(Bool.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return value != 0
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
            if ["1", "true", "yes"].contains(text) { return true }
            if ["0", "false", "no"].contains(text) { return false }
        }
        return nil
    }
}
