//
//  LNGameMateResponse.swift
//  Lanu
//
//  Created by OneeChan on 2025/11/20.
//

import Foundation
import AutoCodable


@AutoCodable
class LNGameMateListItemVO: Decodable {
    var id: String = ""
    var online: Bool = false
    var orderCount: Int = 0
    var distance: Double = 0.0
    var avatar: String = ""
    var nickname: String = ""
    var userNo: String = ""
    var age: Int = 0
    var gender: LNUserGender = .unknow
    var star: Double = 0.0
    var area: String = ""
    var summary: String = ""
    var images: [String] = []
    var voiceBar: String = ""
    var price: Double = 0
    var unit: String = ""
    var labels: [String] = []
    var categoryName: String = ""
    var categoryIcon: String = ""
    var newcomer: Bool = false
}

@AutoCodable
class LNGameMateListResponse: Decodable {
    var list: [LNGameMateListItemVO] = []
    var next: String = ""
}

enum LNGameCategoryType: Int, Decodable {
    case normal = 0
    case offline = 1
    case user = 2
}

@AutoCodable
class LNGameCategoryItemVO: Decodable {
    var code: String = ""
    var name: String = ""
    var icon: String = ""
    var categoryType: LNGameCategoryType = .normal
    
    init(code: String, name: String, icon: String, categoryType: LNGameCategoryType) {
        self.code = code
        self.name = name
        self.icon = icon
        self.categoryType = categoryType
    }
}

@AutoCodable
class LNGameTypeItemVO: Decodable {
    var code: String = ""
    var name: String = ""
    var icon: String = ""
    var categoryType: LNGameCategoryType = .normal
    var children: [LNGameCategoryItemVO] = []
}

@AutoCodable
class LNGameTypeListResponse: Decodable {
    var list: [LNGameTypeItemVO] = []
}

@AutoCodable
class LNGameMateSkillVO: Decodable, Equatable {
    var id: String = ""
    var name: String = ""
    var icon: String = ""
    var price: Double = 0
    var unit: String = ""
    var cover: String = ""
    
    static func == (lhs: LNGameMateSkillVO, rhs: LNGameMateSkillVO) -> Bool {
        lhs.id == rhs.id
        && lhs.name == rhs.name
        && lhs.icon == rhs.icon
        && lhs.price == rhs.price
        && lhs.unit == rhs.unit
        && lhs.cover == rhs.cover
    }
    
    init() { }
}

@AutoCodable
class LNGameMateSkillListResponse: Decodable {
    var list: [LNGameMateSkillVO] = []
}

@AutoCodable
class LNGameMateInfoResponse: Decodable {
    var avatar: String = ""
    var nickname: String = ""
    var age: Int = 0
    var gender: LNUserGender = .unknow
    var star: Double = 0.0
    var area: String = ""
    var cover: String = ""
    var userNo: String = ""
    var languageNames: [String] = []
    var photos: [String] = []
    var intro: String = ""
    var playmate: Bool = false
    var skills: [LNGameMateSkillVO] = []
    var follow: Bool = false
    var fansCount: Int = 0
    var voiceBar: String = ""
    var rated: Bool = false
}

@AutoCodable
class LNGameMateSkillDetailVO: Decodable {
    var id: String = ""
    var avatar: String = ""
    var nickname: String = ""
    var age: Int = 0
    var gender: LNUserGender = .unknow
    var star: Double = 0.0
    var area: String = ""
    var cover: String = ""
    var userNo: String = ""
    var categoryName: String = ""
    var languageNames: [String] = []
    var summary: String = ""
    var images: [String] = []
    var voiceBar: String = ""
    var price: Double = 0
    var unit: String = ""
    var labels: [String] = []
    var categoryCode: String = ""
    var orderCount: Int = 0
    var online: Bool = false
    var follow: Bool = false
    var distance: Double = 0
}

@AutoCodable
class LNGameMateSearchResultVO: Decodable {
    var userNo: String = ""
    var avatar: String = ""
    var nickname: String = ""
    var age: Int = 0
    var gender: LNUserGender = .unknow
    var follow: Bool = false
    var fansCount: Int = 0
    var online: Bool = false
}

@AutoCodable
class LNGameMateSearchResponse: Decodable {
    var list: [LNGameMateSearchResultVO] = []
    var next: String = ""
}

@AutoCodable
class LNJoinUsBindPhoneInfoVO: Decodable {
    var mobileCode: String = ""
    var mobileNum: String = ""
}

@AutoCodable
class LNJoinUsBaseInfoVO: Decodable {
    var avatar: String = ""
    var nickname: String = ""
    var gender: LNUserGender = .unknow
    var birthday: String = ""
    var languageCodes: [String] = []
    var intro: String = ""
    
    init() { }
}

@AutoCodable
class LNSkillFieldValidateLenLimit: Decodable {
    var min: Int = 0
    var max: Int = 0
}

@AutoCodable
class LNSkillFieldValidateNumLimit: Decodable {
    var min: Double = 0
    var max: Double = 0
}

@AutoCodable
class LNSkillFieldValidate: Decodable {
    var required: Bool = false
    var size: LNSkillFieldValidateLenLimit?
    var numLimit: LNSkillFieldValidateNumLimit?
    var arraySize: LNSkillFieldValidateLenLimit?
    var regex: String = ""
    
    init() { }
}

enum LNSkillFieldExampleType: Int, Decodable {
    case photo = 0
    case voice = 1
}

@AutoCodable
class LNSkillFieldExample: Decodable {
    var type: LNSkillFieldExampleType = .photo
    var value: String = ""
    var title: String = ""
    var desc: String = ""
    
    init() { }
}

enum LNSkillFieldValueType: Int, Decodable {
    case unknown = -1
    case string = 0
    case int = 1
    case double = 2
}

enum LNSkillFieldInputType: Int, Decodable {
    case unknown = -1
    case singleLineText = 0
    case multiLineText = 1
    case singleSelection = 2
    case multiSelection = 3
    case number = 4
    case photo = 5
//    case date = 6
    case voice = 7
}

@AutoCodable
class LNSkillFieldConstants: Decodable {
    var value: String = ""
    var key: String = ""
}

enum LNSkillEditStaticFieldCode: String {
    case fieldUnitPrice
    case fieldUnit
}

class LNSkillEditField: Decodable {
    var fieldCode: String = ""
    var value: (any Codable)? = nil
    var fieldName: String = ""
    var fieldDesc: String = ""
    var valueClassType: LNSkillFieldValueType = .string
    var type: LNSkillFieldInputType = .singleLineText
    var array: Bool = false
    var duration: Int = 0
    var constants: [LNSkillFieldConstants] = []
    var validate: LNSkillFieldValidate = LNSkillFieldValidate()
    var example: LNSkillFieldExample?
    
    enum CodingKeys: String, CodingKey {
        case fieldCode
        case value
        case fieldName
        case fieldDesc
        case valueClassType
        case type
        case array
        case duration
        case constants
        case validate
        case example
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        if let value = try? container.decode(String.self, forKey: .fieldCode) {
            self.fieldCode = value
        }
        if let value = try? container.decode(String.self, forKey: .fieldName) {
            self.fieldName = value
        }
        if let value = try? container.decode(String.self, forKey: .fieldDesc) {
            self.fieldDesc = value
        }
        if let value = try? container.decode(LNSkillFieldValueType.self, forKey: .valueClassType) {
            self.valueClassType = value
        }
        if let value = try? container.decode(LNSkillFieldInputType.self, forKey: .type) {
            self.type = value
        }
        if let value = try? container.decode(Bool.self, forKey: .array) {
            self.array = value
        }
        if let value = try? container.decode(Int.self, forKey: .duration) {
            self.duration = value
        }
        if let value = try? container.decode([LNSkillFieldConstants].self, forKey: .constants) {
            self.constants = value
        }
        if let value = try? container.decode(LNSkillFieldValidate.self, forKey: .validate) {
            self.validate = value
        }
        if let value = try? container.decode(LNSkillFieldExample?.self, forKey: .example) {
            self.example = value
        }
        if array {
            switch valueClassType {
            case .string:
                value = try? container.decode([String].self, forKey: .value)
            case .int:
                value = try? container.decode([Int].self, forKey: .value)
            case .double:
                value = try? container.decode([Double].self, forKey: .value)
            case .unknown: break
            }
        } else {
            switch valueClassType {
            case .string:
                value = try? container.decode(String.self, forKey: .value)
            case .int:
                value = try? container.decode(Int.self, forKey: .value)
            case .double:
                value = try? container.decode(Double.self, forKey: .value)
            case .unknown: break
            }
        }
    }
}

@AutoCodable
class LNCreateSkillInputFieldsVO: Decodable {
    var bizCategoryCode: String?
    var fields: [LNSkillEditField] = []
    
    var isAvailable: Bool {
        for field in fields {
            if field.valueClassType == .unknown
                || field.type == .unknown {
                return false
            }
        }
        return true
    }
}

@AutoCodable
class LNJoinUsInputInfosResponse: Decodable {
    var underReview: Bool = false
    var step1Complete: Bool = false
    var step2Complete: Bool = false
    var step3Complete: Bool = false
    var setp1: LNJoinUsBindPhoneInfoVO?
    var setp2: LNJoinUsBaseInfoVO?
    var setp3: LNCreateSkillInputFieldsVO?
}

enum LNOrderAcceptWeekDay: Int, Decodable, CaseIterable {
    case sun = 1
    case mon = 2
    case tue = 3
    case wed = 4
    case thu = 5
    case fri = 6
    case sat = 7
    
    var text: String {
        let formatter = DateFormatter()
        formatter.locale = curLocal
        return formatter.weekdaySymbols[rawValue - 1]
    }
}

@AutoCodable
class LNOrderAcceptConfig: Decodable {
    var timeRange: String = ""
    var weekNums: [LNOrderAcceptWeekDay] = []
    var autoWelcomeOpen: Bool = false
    
    init() { }
}

@AutoCodable
class LNMySkillItemVO: Decodable {
    var id: String = ""
    var bizCategoryName: String = ""
    var categoryIcon: String = ""
    var price: Double = 0.0
    var unit: String = ""
    var open: Bool = false
    var bizCategoryCode: String = ""
}

@AutoCodable
class LNMySkillListResponse: Decodable {
    var list: [LNMySkillItemVO] = []
}

@AutoCodable
class LNGameMateManagerInfo: Decodable {
    var weekBeanIncome: Double = 0
    var exposureCountDay: Int = 0
    var visitorCount: Int = 0
    var playmateOpen: Bool = false
    var potentialUserCount: Int = 0
}

@AutoCodable
class LNVisitorItemVO: Decodable {
    var userNO: String = ""
    var nickname: String = ""
    var avatar: String = ""
    var gender: LNUserGender = .unknow
    var age: Int = 0
    var online: Bool = false
    var visitTime: Int = 0
    var intro: String = ""
    
    init() { }
}

@AutoCodable
class LNVisitorsListResponse: Decodable {
    var list: [LNVisitorItemVO] = []
    var next: String = ""
}

@AutoCodable
class LNSkillEditFieldsResponse: Decodable {
    var bizCategoryName: String = ""
    var fields: [LNSkillEditField] = []
    
    var skillId = ""
}

@AutoCodable
class LNSkillSwitchResponse: Decodable {
    var open: Bool = false
    var mainSkill: Bool = false
}

@AutoCodable
class LNSkillFilterConstants: Decodable {
    var key: String = ""
    var value: String = ""
    var icon: String = ""
}

@AutoCodable
class LNSkillFilterField: Decodable {
    var name: String = ""
    var fieldCode: String = ""
    var constants: [LNSkillFieldConstants] = []
}

@AutoCodable
class LNSkillFilterConfig: Decodable {
    var code: String = ""
    var filterFields: [LNSkillFilterField] = []
}

@AutoCodable
class LNSkillFilterConfigList: Decodable {
    var list: [LNSkillFilterConfig] = []
}

@AutoCodable
class LNSkillCommentVO: Decodable {
    var time: Int = 0
    var avatar: String = ""
    var nickname: String = ""
    var star: Double = 0
    var userNo: String = ""
    var comment: String = ""
}

@AutoCodable
class LNSkillCommentListResponse: Decodable {
    var list: [LNSkillCommentVO] = []
    var next: String = ""
    var total: Int = 0
}

enum LNAutoReplyState: Int, Decodable {
    case reviewing = 0
    case pass = 1
    case reject = 2
}

enum LNAutoReplyType: Int, Decodable {
    case text = 0
    case voice = 1
}

@AutoCodable
class LNAutoReplyVO: Decodable {
    var id: String = ""
    var type: LNAutoReplyType = .text
    var status: LNAutoReplyState = .reviewing
    var textContent: String = ""
    var voiceUrl: String = ""
    var voiceDuration: Int = 0
    var reviewReason: String = ""
    
    init() { }
}

@AutoCodable
class LNAutoReplyResponse: Decodable {
    var list: [LNAutoReplyVO] = []
}

@AutoCodable
class LNAutoReplyQuotaResponse: Decodable {
    var userQuotaCount: Int = 0
    var playmateQuotaCount: Int = 0
}

@AutoCodable
class LNPotentialUserVO: Decodable {
    var userNo: String = ""
    var avatar: String = ""
    var nickname: String = ""
    var age: Int = 0
    var gender: LNUserGender = .unknow
    var newRegister: Bool = false
    var online: Bool = false
    var contacted: Bool = false
}

@AutoCodable
class LNPotentialUsersResponse: Decodable {
    var list: [LNPotentialUserVO] = []
}

@AutoCodable
class LNRoomItemVO: Decodable {
    var roomId: String = ""
    var roomTitle: String = ""
    var roomCover: String = ""
    var user: LNRoomUserVO = LNRoomUserVO()
    
    init( ) { }
}

@AutoCodable
class LNSearchRoomResponse: Decodable {
    var list: [LNRoomItemVO] = []
    var next: String = ""
}

@AutoCodable
class LNMixSearchResponse: Decodable {
    var playmate: [LNGameMateSearchResultVO] = []
    var rooms: [LNRoomItemVO] = []
}
