import Foundation

struct FetchGroupModel: Codable {
    
    let api_status : Int?
    let data : [GroupData]?
    
    enum CodingKeys: String, CodingKey {
        
        case api_status = "api_status"
        case data = "data"
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        api_status = try values.decodeIfPresent(Int.self, forKey: .api_status)
        data = try values.decodeIfPresent([GroupData].self, forKey: .data)
    }
    
}

struct CreateGroupModel: Codable {
    
    let apiStatus: Int?
    let data: [GroupData]?
    
    enum CodingKeys: String, CodingKey {
        case apiStatus = "api_status"
        case data
    }
    
}

class GroupChatModel {
    
    struct GroupChatSuccessModel: Codable {
        let apiStatus: Int?
        let data: DataClass?
        
        enum CodingKeys: String, CodingKey {
            case apiStatus = "api_status"
            case data
        }
    }
    
    struct DataClass: Codable {
        
        let groupID, userID, groupName: String?
        let avatar: String?
        let time: String?
        let messages: [MessageModel]?
        
        enum CodingKeys: String, CodingKey {
            case groupID = "group_id"
            case userID = "user_id"
            case groupName = "group_name"
            case avatar, time, messages
        }
    }
    
}

struct GroupMessageModel: Codable {
    
    let api_status: Int?
    let message_data: String?
    
    enum CodingKeys: String, CodingKey {
        case api_status = "api_status"
        case message_data = "message_data"
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        api_status = try values.decodeIfPresent(Int.self, forKey: .api_status)
        message_data = try values.decodeIfPresent(String.self, forKey: .message_data)
    }
    
}

struct UpdateGroupModel: Codable {
    
    let apiStatus: Int?
    let data: [GroupData]?
    
    enum CodingKeys: String, CodingKey {
        case apiStatus = "api_status"
        case data
    }
    
}

class SendMessageToGroupModel {
    
    struct SendMessageToGroupSuccessModel: Codable {
        let apiStatus: Int?
        let data: [Datum]?
        
        enum CodingKeys: String, CodingKey {
            case apiStatus = "api_status"
            case data
        }
    }
    
    struct Datum: Codable {
        let id, fromID, groupID, pageID: String?
        let toID, text, media, mediaFileName: String?
        let mediaFileNames, time, seen, deletedOne: String?
        let deletedTwo, sentPush, notificationID, typeTwo: String?
        let stickers, productID: String?
        let userData: UserData?
        let onwer: Int?
        let timeText, position, type: String?
        let messageHashID: String?
        
        enum CodingKeys: String, CodingKey {
            case id
            case fromID = "from_id"
            case groupID = "group_id"
            case pageID = "page_id"
            case toID = "to_id"
            case text, media, mediaFileName, mediaFileNames, time, seen
            case deletedOne = "deleted_one"
            case deletedTwo = "deleted_two"
            case sentPush = "sent_push"
            case notificationID = "notification_id"
            case typeTwo = "type_two"
            case stickers
            case productID = "product_id"
            case userData = "user_data"
            case onwer
            case timeText = "time_text"
            case position
            case type = "type"
            case messageHashID = "message_hash_id"
        }
    }
    
}

struct GroupData: Codable {
    
    let group_id : String?
    let user_id : String?
    let group_name : String?
    let avatar : String?
    let time : String?
    let user_data : UserData?
    let owner : Bool?
    let last_message : LastMessageUnion?
    let parts : [UserData]?
    let last_seen : [String]?
    let chat_time : String?
    let chat_id : String?
    let mute : MuteModel?
    
    enum CodingKeys: String, CodingKey {
        
        case group_id = "group_id"
        case user_id = "user_id"
        case group_name = "group_name"
        case avatar = "avatar"
        case time = "time"
        case user_data = "user_data"
        case owner = "owner"
        case last_message = "last_message"
        case parts = "parts"
        case last_seen = "last_seen"
        case chat_time = "chat_time"
        case chat_id = "chat_id"
        case mute = "mute"
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        group_id = try values.decodeIfPresent(String.self, forKey: .group_id)
        user_id = try values.decodeIfPresent(String.self, forKey: .user_id)
        group_name = try values.decodeIfPresent(String.self, forKey: .group_name)
        avatar = try values.decodeIfPresent(String.self, forKey: .avatar)
        time = try values.decodeIfPresent(String.self, forKey: .time)
        user_data = try values.decodeIfPresent(UserData.self, forKey: .user_data)
        owner = try values.decodeIfPresent(Bool.self, forKey: .owner)
        last_message = try values.decodeIfPresent(LastMessageUnion.self, forKey: .last_message)
        parts = try values.decodeIfPresent([UserData].self, forKey: .parts)
        last_seen = try values.decodeIfPresent([String].self, forKey: .last_seen)
        chat_time = try values.decodeIfPresent(String.self, forKey: .chat_time)
        chat_id = try values.decodeIfPresent(String.self, forKey: .chat_id)
        mute = try values.decodeIfPresent(MuteModel.self, forKey: .mute)
    }
    
}

enum LastMessageUnion: Codable {
    
    case anythingArray([JSONAny])
    case lastMessage(MessageModel)
    
    var last_message: MessageModel? {
        switch self {
        case let .anythingArray(value):
            return nil
        case let .lastMessage(value):
            return value
        }
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode([JSONAny].self) {
            self = .anythingArray(x)
            return
        }
        if let x = try? container.decode(MessageModel.self) {
            self = .lastMessage(x)
            return
        }
        throw DecodingError.typeMismatch(LastMessageUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for LastMessageUnion"))
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .anythingArray(let x):
            try container.encode(x)
        case .lastMessage(let x):
            try container.encode(x)
        }
    }
    
}
