package com.yutou.napcat.event;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap;
import com.yutou.napcat.QQDatabase;
import com.yutou.napcat.enums.MessageEnum;
import com.yutou.napcat.handle.*;
import com.yutou.napcat.model.AppShareBean;
import com.yutou.napcat.model.Message;
import com.yutou.napcat.model.SourceFrom;
import lombok.Data;
import lombok.val;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Data
public class MessageEvent {

    @JSONField(name = "self_id")
    private Long selfId;

    @JSONField(name = "user_id")
    private Long userId;

    @JSONField(name = "time")
    private Long time;

    @JSONField(name = "message_id")
    private Integer messageId;

    @JSONField(name = "real_id")
    private Integer realId;

    @JSONField(name = "message_type")
    private String messageType;

    @JSONField(name = "sender")
    private SourceFrom source;

    @JSONField(name = "raw_message")
    private String rawMessage;

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

    @JSONField(name = "sub_type")
    private String subType;

    @JSONField(name = "message")
    private List<BaseHandle<?>> message;

    @JSONField(name = "message_format")
    private String messageFormat;

    @JSONField(name = "post_type")
    private String postType;

    @JSONField(name = "group_id")
    private Long groupId;


    public static MessageEvent parseHandleHttp(String jsonString) {
        return parseHandle(JSONObject.parseObject(jsonString).getJSONObject("data").toString());
    }

    public static MessageEvent parseHandle(String jsonString) {
        JSONObject json = JSONObject.parseObject(jsonString);
        JSONArray array = json.getJSONArray("message");
        List<BaseHandle<?>> messageList = new ArrayList<>();
        if (array != null) {
            for (Object o : array) {
                JSONObject _json = (JSONObject) o;
                Type classType = null;
                MessageEnum _type = MessageEnum.of(_json.getString("type"));
                classType = switch (_type) {
                    case TEXT -> Text.TextInfo.class;
                    case IMAGE -> Image.ImageInfo.class;
                    case AT -> At.AtData.class;
                    case JSON -> OtherHandle.OtherInfo.class;
                    case REPLY -> Reply.ReplyInfo.class;
                    default -> classType;
                };
                BaseHandle<?> handle = new BaseHandle<>(_type.getType());
                if (_type == MessageEnum.JSON) {
                    handle.setData(JSONObject.parseObject(((JSONObject) o).getJSONObject("data").getString("data"), classType));
                } else {
                    handle.setData(JSONObject.parseObject(((JSONObject) o).getJSONObject("data").toString(), classType));
                }
                messageList.add(handle);
            }
        }
        MessageEvent event = new MessageEvent();
        event.setTime(json.getLong("time"));
        event.setSelfId(json.getLong("self_id"));
        event.setPostType(json.getString("post_type"));
        event.setGroupId(json.getLong("group_id"));
        event.setUserId(json.getLong("user_id"));
        event.setSubType(json.getString("sub_type"));
        try {
            SourceFrom sender = new SourceFrom();
            sender.setUserId(event.getUserId());
            event.setSource(sender);
            sender.setUserId(json.getJSONObject("sender").getLong("user_id"));
            sender.setNickname(json.getJSONObject("sender").getString("nickname"));
            sender.setCard(json.getJSONObject("sender").getString("card"));
            event.setMessageId(json.getInteger("message_id"));
            event.setRealId(json.getInteger("real_id"));
            event.setMessageType(json.getString("message_type"));
            event.setSource(sender);
            event.setRawMessage(json.getString("raw_message"));
            event.setFont(json.getInteger("font"));
            event.setMessageFormat(json.getString("message_format"));
            event.setMessage(messageList);
            return event;
        } catch (Exception e) {
            System.err.println("jsonString:\n" + jsonString);
        }
        return event;
    }

    public boolean hasType(MessageEnum messageEnum) {
        if(message==null||message.isEmpty()){
            return false;
        }
        for (BaseHandle<?> handle : message) {
            if (MessageEnum.of(handle.getType()) == messageEnum) {
                return true;
            }
        }
        return false;
    }

    public <T extends BaseHandle> List<T> findAllType(Class<T> t) {
        List<T> tmp = new ArrayList<>();
        if (message == null || message.isEmpty()) {
            return tmp;
        }
        try {
            T newed = t.getDeclaredConstructor().newInstance();
            for (BaseHandle<?> baseHandle : message) {
                if (baseHandle.getType().equals(newed.getType())) {
                    newed.setData(baseHandle.getData());
                    tmp.add(newed);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tmp;
    }

    public <T extends BaseHandle> T findType(Class<T> tClass) {
        List<T> list = findAllType(tClass);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }


    public boolean isAtMe() {
        if (!hasType(MessageEnum.AT)) {
            return false;
        }
        List<At> list = findAllType(At.class);
        for (At handle : list) {
            if (handle.getData().getQq() == QQDatabase.getMe().getUserId()) {
                return true;
            }
        }
        return false;
    }

    public String getTextMessage() {
        val texts = findAllType(Text.class);
        StringBuilder sb = new StringBuilder();
        for (Text text : texts) {
            sb.append(text);
        }
        return sb.toString().trim();
    }

    public boolean isUser() {
        return "private".equals(messageType);
    }

    public boolean isGroup() {
        return "group".equals(messageType);
    }


}
