package cn.reghao.tnb.content.app.chat.service;

import cn.reghao.file.api.dto.ObjectMeta;
import cn.reghao.file.api.iface.OssService;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.string.SnowFlake;
import cn.reghao.tnb.common.auth.UserContext;
import cn.reghao.tnb.content.app.chat.db.mapper.*;
import cn.reghao.tnb.content.app.chat.model.constant.MsgType;
import cn.reghao.tnb.content.app.chat.model.dto.chat.ChatRecordGetRet;
import cn.reghao.tnb.content.app.chat.model.dto.message.*;
import cn.reghao.tnb.content.app.chat.model.po.chat.ChatDialog;
import cn.reghao.tnb.content.app.chat.model.po.chat.ChatRecord;
import cn.reghao.tnb.content.app.chat.model.po.message.CodeBlockMessage;
import cn.reghao.tnb.content.app.chat.model.po.message.FileMessage;
import cn.reghao.tnb.content.app.chat.model.po.message.TextMessage;
import cn.reghao.tnb.message.api.model.resp.EvtTalkRevokeResp;
import cn.reghao.tnb.user.api.dto.ContactDetail;
import cn.reghao.tnb.user.api.iface.UserContactService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author reghao
 * @date 2022-04-30 15:08:12
 */
@Service
public class ChatMessageService {
    @DubboReference(check = false)
    private UserContactService contactService;
    @DubboReference(check = false)
    private OssService ossService;

    private final ChatDialogMapper chatDialogMapper;
    private final ChatRecordMapper chatRecordMapper;
    private final TextMessageMapper textMessageMapper;
    private final CodeBlockMessageMapper codeBlockMessageMapper;
    private final FileMessageMapper fileMessageMapper;
    private final SnowFlake snowFlake;
    private final EventService eventService;

    public ChatMessageService(ChatDialogMapper chatDialogMapper, ChatRecordMapper chatRecordMapper,
                              TextMessageMapper textMessageMapper, CodeBlockMessageMapper codeBlockMessageMapper,
                              FileMessageMapper fileMessageMapper, EventService eventService) {
        this.chatDialogMapper = chatDialogMapper;
        this.chatRecordMapper = chatRecordMapper;
        this.textMessageMapper = textMessageMapper;
        this.codeBlockMessageMapper = codeBlockMessageMapper;
        this.fileMessageMapper = fileMessageMapper;
        this.snowFlake = new SnowFlake(1L, 1L);
        this.eventService = eventService;
    }

    public void sendTextMessage(TextMsg textMsg) {
        long loginUser = UserContext.getUserId();
        long receiverId = textMsg.getReceiverId();
        int chatType = textMsg.getTalkType();

        ChatDialog chatDialog = chatDialogMapper.findByReceiverAndUserId(receiverId, loginUser);
        long chatId = chatDialog.getChatId();

        long recordId = snowFlake.nextId();
        ChatRecord chatRecord = new ChatRecord(recordId, chatId, chatType, loginUser, receiverId, MsgType.text.getCode());
        chatRecordMapper.save(chatRecord);

        String text = textMsg.getText();
        TextMessage textMessage = new TextMessage(recordId, text);
        textMessageMapper.save(textMessage);

        ContactDetail contactDetail = contactService.getContactDetail(loginUser);
        ChatRecordGetRet chatRecordGetRet = new ChatRecordGetRet(chatRecord, contactDetail);
        chatRecordGetRet.setContent(textMessage.getContent());
        eventService.sendMessageEvent(chatType, loginUser, receiverId, chatRecordGetRet);
    }

    public void sendEmoticonMessage(EmoticonMsg emoticonMsg) {
    }

    public void sendImageMessage(ImageMsg imageMsg) {
        long loginUser = UserContext.getUserId();
        long receiverId = imageMsg.getReceiverId();
        int chatType = imageMsg.getTalkType();
        String uploadId = imageMsg.getUploadId();

        try {
            int channelCode = 110;
            ObjectMeta objectMeta = ossService.getObjectMeta(uploadId);
            if (objectMeta == null) {
                return;
            }

            String signedUrl = ossService.getSignedUrl(uploadId, null);
            String filename = objectMeta.getFilename();
            String suffix = getSuffix(filename);
            int fileType = objectMeta.getFileType();
            /*int width = objectInfo.getWidth();
            int height = objectInfo.getHeight();*/
            int width = 480;
            int height = 320;

            ChatDialog chatDialog = chatDialogMapper.findByReceiverAndUserId(receiverId, loginUser);
            long chatId = chatDialog.getChatId();
            long recordId = snowFlake.nextId();

            ChatRecord chatRecord = new ChatRecord(recordId, chatId, chatType, loginUser, receiverId, MsgType.media.getCode());
            FileMessage fileMessage = new FileMessage(fileType, recordId, uploadId, filename);
            fileMessage.setWidth(width);
            fileMessage.setHeight(height);
            chatRecordMapper.save(chatRecord);
            fileMessageMapper.save(fileMessage);

            ContactDetail contactDetail = contactService.getContactDetail(loginUser);
            ChatRecordGetRet chatRecordGetRet = new ChatRecordGetRet(chatRecord, contactDetail);
            String createAt = DateTimeConverter.format(chatRecord.getCreateTime());
            FileMsgResult fileMsgResult = new FileMsgResult(fileMessage, signedUrl, loginUser, createAt);
            chatRecordGetRet.setFile(fileMsgResult);
            eventService.sendMessageEvent(chatType, loginUser, receiverId, chatRecordGetRet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getSuffix(String filename) {
        int idx = filename.lastIndexOf(".");
        return idx == -1 ? "" : filename.substring(idx);
    }

    public void sendFileMessage(FileMsg fileMsg) throws IOException {
        long loginUser = UserContext.getUserId();
        long receiverId = fileMsg.getReceiverId();
        int chatType = fileMsg.getTalkType();
        String uploadId = fileMsg.getUploadId();

        try {
            int channelCode = 110;
            ObjectMeta objectMeta = ossService.getObjectMeta(uploadId);
            if (objectMeta == null) {
                return;
            }
            int fileType = objectMeta.getFileType();
            String filename = objectMeta.getFilename();

            ChatDialog chatDialog = chatDialogMapper.findByReceiverAndUserId(receiverId, loginUser);
            long chatId = chatDialog.getChatId();
            long recordId = snowFlake.nextId();

            ChatRecord chatRecord = new ChatRecord(recordId, chatId, chatType, loginUser, receiverId, MsgType.media.getCode());
            FileMessage fileMessage = new FileMessage(fileType, recordId, uploadId, filename);
            chatRecordMapper.save(chatRecord);
            fileMessageMapper.save(fileMessage);

            String signedUrl = ossService.getSignedUrl(uploadId, null);
            ContactDetail contactDetail = contactService.getContactDetail(loginUser);
            ChatRecordGetRet chatRecordGetRet = new ChatRecordGetRet(chatRecord, contactDetail);
            String createAt = DateTimeConverter.format(chatRecord.getCreateTime());
            FileMsgResult fileMsgResult = new FileMsgResult(fileMessage, signedUrl, loginUser, createAt);
            chatRecordGetRet.setFile(fileMsgResult);
            eventService.sendMessageEvent(chatType, loginUser, receiverId, chatRecordGetRet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendChatRecordMessage(ForwardMsg forwardMsg) {
    }

    public void sendCodeBlockMessage(CodeBlockMsg codeBlockMsg) throws IOException {
        long loginUser = UserContext.getUserId();
        long receiverId = codeBlockMsg.getReceiverId();
        int chatType = codeBlockMsg.getTalkType();

        ChatDialog chatDialog = chatDialogMapper.findByReceiverAndUserId(receiverId, loginUser);
        long chatId = chatDialog.getChatId();
        long recordId = snowFlake.nextId();
        ChatRecord chatRecord = new ChatRecord(recordId, chatId, chatType, loginUser, receiverId, MsgType.codeBlock.getCode());
        chatRecordMapper.save(chatRecord);

        String lang = codeBlockMsg.getLang();
        String code = codeBlockMsg.getCode();
        CodeBlockMessage codeBlockMessage = new CodeBlockMessage(recordId, lang, code);
        codeBlockMessageMapper.save(codeBlockMessage);

        CodeBlockResult codeBlockResult = new CodeBlockResult(codeBlockMessage, loginUser);
        ContactDetail contactDetail = contactService.getContactDetail(loginUser);
        ChatRecordGetRet chatRecordGetRet = new ChatRecordGetRet(chatRecord, contactDetail);
        chatRecordGetRet.setCodeBlock(codeBlockResult);
        eventService.sendMessageEvent(chatType, loginUser, receiverId, chatRecordGetRet);
    }

    public void sendVoteMessage(VoteMsg voteMsg) {
    }

    public void revokeChatRecord(long recordId) throws IOException {
        chatRecordMapper.updateSetRevoke(recordId);

        ChatRecord chatRecord = chatRecordMapper.findByRecordId(recordId);
        int chatType = chatRecord.getChatType();
        long senderId = chatRecord.getSenderId();
        long receiverId = chatRecord.getReceiverId();

        EvtTalkRevokeResp resp = new EvtTalkRevokeResp(chatType, senderId, receiverId, recordId);
        eventService.sendMessageEvent(senderId, receiverId, resp);
    }

    public void deleteChatRecord(long recordId) {
    }

    public String putImageMessage(ImageMessage imageMessage) throws Exception {
        int channelCode = imageMessage.getChannelCode();
        String uploadId = imageMessage.getUploadId();
        return ossService.getSignedUrl(uploadId, null);
    }

    public List<DateDto> getDateList() {
        List<DateDto> list = new ArrayList<>();
        list.add(new DateDto(LocalDate.now().toString(), 1));
        list.add(new DateDto(LocalDate.of(2024, 4, 1).toString(), 1));
        list.add(new DateDto(LocalDate.of(2024, 4, 2).toString(), 2));
        list.add(new DateDto(LocalDate.of(2024, 4, 3).toString(), 3));
        list.add(new DateDto(LocalDate.of(2024, 4, 4).toString(), 4));
        return list;
    }
}
