package com.yonge.cooleshow.biz.dal.dto;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.yonge.cooleshow.biz.dal.enums.im.ETencentGroupType;
import com.yonge.cooleshow.biz.dal.enums.im.ETencentImCallbackCommand;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

/**
 * Description
 *
 * @author liujunchi
 * @date 2023-03-06
 */
@NoArgsConstructor
@Data
public class TencentData {

    // 群成员离开之后回调对象
    @NoArgsConstructor
    @Data
    public static class CallbackAfterMemberExit {


        private String clientIP;

        private String optPlatform;

        // 回调命令
        private ETencentImCallbackCommand callbackCommand;
        // 群组 ID
        private String groupId;
        // 群组类型
        private ETencentGroupType type;
        // 成员离开方式：Kicked-被踢；Quit-主动退群
        private String exitType;
        // 操作者
        private String operatorAccount;
        // 离开群的成员列表
        private List<MemberListDTO> exitMemberList;
        //毫秒级别，事件触发时间戳
        private LocalDateTime eventTime;

        public static CallbackAfterMemberExit toObject(String jsonString) {

            CallbackAfterMemberExit res = new CallbackAfterMemberExit();

            JSONObject jsonObject = JSON.parseObject(jsonString);
            res.setCallbackCommand(ETencentImCallbackCommand.valueOf(jsonObject.getString("CallbackCommand").replace(".","_").toUpperCase(
                Locale.ROOT)));
            res.setGroupId(jsonObject.getString("GroupId"));
            res.setType(jsonObject.getObject("Type",ETencentGroupType.class));
            res.setExitType(jsonObject.getString("ExitType"));
            res.setOperatorAccount(jsonObject.getString("Operator_Account"));

            JSONArray exitMemberList = jsonObject.getJSONArray("ExitMemberList");
            if (!exitMemberList.isEmpty()) {
                List<MemberListDTO> memberListDTOS = new ArrayList<>();
                for (int i = 0; i < exitMemberList.size(); i++) {
                    MemberListDTO memberListDTO = new MemberListDTO();
                    JSONObject exitMemberListJSONObject = exitMemberList.getJSONObject(i);
                    String member_account = exitMemberListJSONObject.getString("Member_Account");
                    memberListDTO.setMemberAccount(member_account);
                    memberListDTOS.add(memberListDTO);
                }
                res.setExitMemberList(memberListDTOS);
            }



            res.setEventTime(((Timestamp)jsonObject.getTimestamp("EventTime")).toLocalDateTime());

            return res;
        }
    }

    @NoArgsConstructor
    @Data
    public static class MemberListDTO {
        private String memberAccount;
    }

    // 直播群成员在线状态回调
    @NoArgsConstructor
    @Data
    public static class CallbackOnMemberStateChange {

        // 客户端平台，对应不同的平台类型，可能的取值有：
        // RESTAPI（使用 REST API 发送请求）、Web（使用 Web SDK 发送请求）、
        // Android、iOS、Windows、Mac、iPad、Unknown（使用未知类型的设备发送请求）
        private String clientIP;

        private String optPlatform;
        // 回调命令
        private ETencentImCallbackCommand callbackCommand;
        // 群组 ID
        private String groupId;
        // 事件类型：Offline - 掉线、Online - 重新上线
        private String eventType;
        // 离开群的成员列表
        private List<MemberListDTO> memberList;

        private Long eventTime;

        public static CallbackOnMemberStateChange toObject(String jsonString) {

            CallbackOnMemberStateChange res = new CallbackOnMemberStateChange();

            JSONObject jsonObject = JSON.parseObject(jsonString);
            res.setCallbackCommand(ETencentImCallbackCommand.valueOf(jsonObject.getString("CallbackCommand").replace(".","_").toUpperCase(
                Locale.ROOT)));
            res.setGroupId(jsonObject.getString("GroupId"));

            JSONArray exitMemberList = jsonObject.getJSONArray("MemberList");
            if (!exitMemberList.isEmpty()) {
                List<MemberListDTO> memberListDTOS = new ArrayList<>();
                for (int i = 0; i < exitMemberList.size(); i++) {
                    MemberListDTO memberListDTO = new MemberListDTO();
                    JSONObject exitMemberListJSONObject = exitMemberList.getJSONObject(i);
                    String member_account = exitMemberListJSONObject.getString("Member_Account");
                    memberListDTO.setMemberAccount(member_account);
                    memberListDTOS.add(memberListDTO);
                }
                res.setMemberList(memberListDTOS);
            }

            res.setEventType(jsonObject.getString("EventType"));
            res.setEventTime(Optional.ofNullable(jsonObject.getLong("EventTime")).orElse(new Date().getTime()));

            return res;
        }
    }

    @NoArgsConstructor
    @Data
    public static class CallbackAfterNewMemberJoin {

        private String clientIP;

        private String optPlatform;
        // 回调命令
        private ETencentImCallbackCommand callbackCommand;
        // 群组 ID
        private String groupId;
        // 群组类型
        private ETencentGroupType type;
        // 入群方式：Apply（申请入群）；Invited（邀请入群）
        private String joinType;
        // 操作者成员
        private String operatorAccount;
        // 新入群成员列表
        private List<MemberListDTO> newMemberList;
        //毫秒级别，事件触发时间戳
        private LocalDateTime eventTime;

        public static CallbackAfterNewMemberJoin toObject(String jsonString) {

            CallbackAfterNewMemberJoin res = new CallbackAfterNewMemberJoin();

            JSONObject jsonObject = JSON.parseObject(jsonString);
            res.setCallbackCommand(ETencentImCallbackCommand.valueOf(jsonObject.getString("CallbackCommand").replace(".","_").toUpperCase(
                Locale.ROOT)));
            res.setGroupId(jsonObject.getString("GroupId"));
            res.setType(jsonObject.getObject("Type",ETencentGroupType.class));
            res.setJoinType(jsonObject.getString("JoinType"));
            res.setOperatorAccount(jsonObject.getString("Operator_Account"));

            JSONArray exitMemberList = jsonObject.getJSONArray("NewMemberList");
            if (!exitMemberList.isEmpty()) {
                List<MemberListDTO> memberListDTOS = new ArrayList<>();
                for (int i = 0; i < exitMemberList.size(); i++) {
                    MemberListDTO memberListDTO = new MemberListDTO();
                    JSONObject exitMemberListJSONObject = exitMemberList.getJSONObject(i);
                    String member_account = exitMemberListJSONObject.getString("Member_Account");
                    memberListDTO.setMemberAccount(member_account);
                    memberListDTOS.add(memberListDTO);
                }
                res.setNewMemberList(memberListDTOS);
            }


            res.setEventTime(((Timestamp)jsonObject.getTimestamp("EventTime")).toLocalDateTime());

            return res;
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("推断流事件回调通知")
    public static class CallbackStreamStateEvent implements Serializable {


        @ApiModelProperty("推流域名")
        @JSONField(name = "app")
        private String app;

        @ApiModelProperty("用户 APPID")
        @JSONField(name = "appid")
        private Integer appid;

        @ApiModelProperty("推流路径")
        @JSONField(name = "appname")
        private String appname;

        @ApiModelProperty("同直播流名称")
        @JSONField(name = "channel_id")
        private String channelId;

        @ApiModelProperty("断流事件通知推流时长，单位毫秒")
        @JSONField(name = "push_duration")
        private String pushDuration;

        @ApiModelProperty("推断流错误码")
        @JSONField(name = "errcode")
        private Integer errcode;

        @ApiModelProperty("推断流错误描述")
        @JSONField(name = "errmsg")
        private String errmsg;

        @ApiModelProperty("事件消息产生的 UNIX 时间戳")
        @JSONField(name = "event_time")
        private Integer eventTime;

        @ApiModelProperty("事件类型: 推流：1；断流：0")
        @JSONField(name = "event_type")
        private Integer eventType;

        @ApiModelProperty("判断是否为国内外推流。1-6为国内，7-200为国外")
        @JSONField(name = "set_id")
        private Integer setId;

        @ApiModelProperty("直播接入点的 IP")
        @JSONField(name = "node")
        private String node;

        @ApiModelProperty("消息序列号，标识一次推流活动，一次推流活动会产生相同序列号的推流和断流消息")
        @JSONField(name = "sequence")
        private String sequence;

        @ApiModelProperty("直播流名称")
        @JSONField(name = "stream_id")
        private String streamId;

        @ApiModelProperty("用户推流 URL 所带参数")
        @JSONField(name = "stream_param")
        private String streamParam;

        @ApiModelProperty("用户推流 IP")
        @JSONField(name = "user_ip")
        private String userIp;

        @ApiModelProperty("视频宽度，最开始推流回调的时候若视频头部信息缺失，可能为0")
        @JSONField(name = "width")
        private Integer width;

        @ApiModelProperty("视频高度，最开始推流回调的时候若视频头部信息缺失，可能为0")
        @JSONField(name = "height")
        private Integer height;

        @ApiModelProperty("事件通知安全签名 sign = MD5（key + t）")
        @JSONField(name = "sign")
        private String sign;

        @ApiModelProperty("过期时间，事件通知签名过期 UNIX 时间戳")
        @JSONField(name = "t")
        private Integer t;

        public static CallbackStreamStateEvent from(String jsonString) {
            return JSON.parseObject(jsonString, CallbackStreamStateEvent.class);
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("流录制事件回调通知")
    public static class CallbackSteamRecordEvent implements Serializable {

        @ApiModelProperty("事件类型：直播录制： 100")
        @JSONField(name = "event_type")
        private Integer eventType;

        @ApiModelProperty("用户 APPID")
        @JSONField(name = "appid")
        private Integer appid;

        @ApiModelProperty("推流域名")
        @JSONField(name = "app")
        private String app;

        @ApiModelProperty("json对象字符串，用户自定义数据")
        @JSONField(name = "callback_ext")
        private String callbackExt;

        @ApiModelProperty("推流路径")
        @JSONField(name = "appname")
        private String appname;

        @ApiModelProperty("直播流名称")
        @JSONField(name = "stream_id")
        private String streamId;

        @ApiModelProperty("同直播流名称")
        @JSONField(name = "channel_id")
        private String channelId;

        @ApiModelProperty("点播 file ID，在 云点播平台 可以唯一定位一个点播视频文件")
        @JSONField(name = "file_id")
        private String fileId;

        @ApiModelProperty("点播文件ID")
        @JSONField(name = "record_file_id")
        private String recordFileId;

        @ApiModelProperty("文件格式： FLV，HLS，MP4，AAC")
        @JSONField(name = "file_format")
        private String fileFormat;

        @ApiModelProperty("录制任务 ID")
        @JSONField(name = "task_id")
        private String taskId;

        @ApiModelProperty("录制任务开始写文件的时间；不能以该值作为录制内容的开始时间，录制内容的开始时间 = end_time – duration")
        @JSONField(name = "start_time")
        private Integer startTime;

        @ApiModelProperty("录制任务结束写文件的时间")
        @JSONField(name = "end_time")
        private Integer endTime;

        @ApiModelProperty("录制任务开始写文件的时间，微秒部分")
        @JSONField(name = "start_time_usec")
        private Integer startTimeUsec;

        @ApiModelProperty("录制任务结束写文件的时间，微秒部分")
        @JSONField(name = "end_time_usec")
        private Integer endTimeUsec;

        @ApiModelProperty("录制文件时长，单位秒")
        @JSONField(name = "duration")
        private Integer duration;

        @ApiModelProperty("录制文件大小，单位字节")
        @JSONField(name = "file_size")
        private Integer fileSize;

        @ApiModelProperty("用户推流 URL 所带参数（自定义）")
        @JSONField(name = "stream_param")
        private String streamParam;

        @ApiModelProperty("录制文件下载 URL")
        @JSONField(name = "video_url")
        private String videoUrl;

        @ApiModelProperty("录制开始拉流收到的首帧 pts ")
        @JSONField(name = "media_start_time")
        private Integer mediaStartTime;

        @ApiModelProperty("录制从转码拉流录制对应的码率（单位 kbps）")
        @JSONField(name = "record_bps")
        private Integer recordBps;

        @ApiModelProperty("事件通知安全签名 sign = MD5（key + t）")
        @JSONField(name = "sign")
        private String sign;

        @ApiModelProperty("过期时间，事件通知签名过期 UNIX 时间戳")
        @JSONField(name = "t")
        private Integer t;


        public static CallbackSteamRecordEvent from(String json) {
            return JSON.parseObject(json, CallbackSteamRecordEvent.class);
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("流异常事件回调通知")
    public static class CallbackStreamExceptionEvent implements Serializable {

        @ApiModelProperty("用户 APPID")
        @JSONField(name = "appid")
        private Integer appid;

        @ApiModelProperty("推流事件回调时间（单位ms）")
        @JSONField(name = "data_time")
        private Long dataTime;

        @ApiModelProperty("推流域名")
        @JSONField(name = "domain")
        private String domain;

        @ApiModelProperty("事件类型：推流异常：321")
        @JSONField(name = "event_type")
        private Integer eventType;

        @JSONField(name = "interface")
        private String interfaceX;
        @JSONField(name = "path")
        private String path;

        @ApiModelProperty("有异常事件时，上报间隔（单位ms）")
        @JSONField(name = "report_interval")
        private Integer reportInterval;

        @JSONField(name = "sequence")
        private String sequence;

        @ApiModelProperty("直播流名称")
        @JSONField(name = "stream_id")
        private String streamId;

        @ApiModelProperty("用户推流 URL 所带参数")
        @JSONField(name = "stream_param")
        private String streamParam;

        @JSONField(name = "timeout")
        private Integer timeout;

        @ApiModelProperty("详细异常事件事件组")
        @JSONField(name = "abnormal_event")
        private String abnormalEvent;

        public static CallbackStreamExceptionEvent from(String json) {
            return JSON.parseObject(json, CallbackStreamExceptionEvent.class);
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("流事件回调结果")
    public static class StreamEventCallbackResult implements Serializable {

        @ApiModelProperty("事件响应状态")
        private Integer code;
    }


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("腾讯云回调事件")
    public static class TRTCEventInfo implements Serializable {

        @JsonProperty("EventGroupId")
        @ApiModelProperty("事件组")
        private Integer eventGroupId;

        @JsonProperty("EventType")
        @ApiModelProperty("事件类型")
        private Integer eventType;

        @JsonProperty("CallbackTs")
        @ApiModelProperty("事件时间")
        private Long callbackTs;

        @JsonProperty("EventInfo")
        @ApiModelProperty("事件消息")
        private EventInfo eventInfo;

        public String jsonString() {
            return JSON.toJSONString(this);
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel("事件消息")
    public static class EventInfo implements Serializable {

        @JsonProperty("RoomId")
        @ApiModelProperty("房间号")
        private String roomId;

        @JsonProperty("EventTs")
        @ApiModelProperty("事件发生时间")
        private Long eventTs;

        @JsonProperty("UserId")
        @ApiModelProperty("事件发生用户")
        private String userId;

        @JsonProperty("Role")
        @ApiModelProperty("用户角色")
        private String role;

        @JsonProperty("TerminalType")
        @ApiModelProperty("终端类型")
        private String terminalType;

        @JsonProperty("UserType")
        @ApiModelProperty("用户类型")
        private String userType;

        @JsonProperty("Reason")
        @ApiModelProperty("原因")
        private String reason;
    }
}
