package com.ruoyi.system.service.md.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.base.CharMatcher;
import com.google.common.collect.Lists;
import com.ruoyi.system.domain.md.NewmsgInbox;
import com.ruoyi.system.domain.md.NewmsgInboxExample;
import com.ruoyi.system.domain.md.NewmsgOutbox;
import com.ruoyi.system.domain.md.enums.BooleanType;
import com.ruoyi.system.domain.md.query.QueryPage;
import com.ruoyi.system.domain.md.request.NewMsgQuery;
import com.ruoyi.system.domain.md.request.NewMsgSendData;
import com.ruoyi.system.domain.md.request.NewMsgUser;
import com.ruoyi.system.domain.md.util.FormInboxExample4Json;
import com.ruoyi.system.listener.MyBaseService;
import com.ruoyi.system.mapper.md.NewmsgInboxMapper;
import com.ruoyi.system.mapper.md.NewmsgOutboxMapper;
import com.ruoyi.system.mapper.md.ext.ExtNewmsgInboxMapper;
import com.ruoyi.system.service.BaseServiceImpl;
import com.ruoyi.system.service.md.NewmsgInboxService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author vidar
 * date 2024/6/6
 * description
 **/
@Service
@MyBaseService
public class NewmsgInboxServiceImpl extends BaseServiceImpl<NewmsgInboxMapper, NewmsgInbox, NewmsgInboxExample> implements NewmsgInboxService {
    @Resource
    private ExtNewmsgInboxMapper extMiddlewareNewmsgInboxMapper;
    @Resource
    private NewmsgOutboxMapper newmsgOutboxMapper;

    @Override
    public int saveInBatch(NewMsgSendData sendData, NewMsgUser from, List<NewMsgUser> toList) {
        List<NewmsgInbox> list = new ArrayList<>();
        for (NewMsgUser u : toList) {
            list.add(initEntity(sendData, from, u));
        }
        return extMiddlewareNewmsgInboxMapper.insertBatch(list);
    }

    @Override
    public IPage<Map<String, Object>> queryUnion(NewMsgQuery query, QueryPage page) {
        NewmsgInboxExample example = buildExample(query);

        IPage<Map<String, Object>> result = new Page<>();
        result.setCurrent(page.getPageNo());
        result.setSize(page.getPageSize());
        int count = (int) extMiddlewareNewmsgInboxMapper.countByExample(example);
        result.setTotal(count);
        result.setPages((int) Math.ceil((double) count / page.getPageSize()));
        if (count == 0) {
            result.setRecords(Collections.EMPTY_LIST);
            return result;
        }
        PageHelper.startPage(page.getPageNo(), page.getPageSize(), false);

        if (StringUtils.isBlank(query.getOrders())) {
            example.setOrderByClause("ctime desc");
        } else {
            example.setOrderByClause("dtime desc");
        }
        List<NewmsgInbox> list = extMiddlewareNewmsgInboxMapper.selectByExample(example);
        List<Map<String, Object>> mapList = inboxListToMap(list);
        result.setRecords(CollectionUtils.isEmpty(mapList) ? Lists.newArrayList() : mapList);
        return result;
    }

    @Override
    public NewmsgInbox getInboxDetail(String id) {
        NewmsgInbox inbox = this.selectByPrimaryKey(id);
        if(inbox == null){
            return null;
        }
        NewmsgOutbox outbox = newmsgOutboxMapper.selectByPrimaryKey(inbox.getOutboxid());
        inbox.setBody(outbox == null ? "" : outbox.getBody());
        return inbox;
    }

    private List<Map<String, Object>> inboxListToMap(List<NewmsgInbox> list) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (NewmsgInbox inbox : list) {
            Map<String, Object> map = inboxToMap(inbox);
            if(StringUtils.isNotBlank(inbox.getBody())){
                map.put("summary",getSummary(inbox.getBody()));
            }else {
                map.put("summary","");
            }
            map.put("body",null);

            mapList.add(map);
        }
        return mapList;
    }

    /**
     * 截取概要
     * @param content
     */
    private  String getSummary(String content){
        if(StringUtils.isBlank(content)){
            return "";
        }

        StringBuilder summary = new StringBuilder();
        try(InputStream iin = new ByteArrayInputStream(content.getBytes())){
            try(Reader in = new InputStreamReader(iin)){
                ParserDelegator delegator = new ParserDelegator();
                delegator.parse(in, new HTMLEditorKit.ParserCallback(){
                    @Override
                    public void handleText(char[] data, int pos) {
                        summary.append(data);
                    }
                }, Boolean.TRUE);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }

        int size = 100;
        if(summary.length()> size){
            return CharMatcher.WHITESPACE.trimFrom(summary.substring(0,size));
        }
        return CharMatcher.WHITESPACE.trimFrom(summary.toString());
    }

    @Override
    public Map<String, Object> inboxToMap(NewmsgInbox inbox) {
        Map<String, Object> map = new HashMap<>();
        try {
            map = JSON.parseObject(JSONObject.toJSONString(inbox));
            if (inbox.getParams() != null) {
                Map<String, Object> params = JSON.parseObject(inbox.getParams().toString());
                map.putAll(params);
                map.remove("params");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    @Override
    public boolean readInbox(NewMsgQuery query) {
        NewmsgInboxExample example = buildExample(query);
        example.getOredCriteria().get(0).andUserreadEqualTo(BooleanType.no.getCode());

        NewmsgInbox record = new NewmsgInbox();
        record.setUserread(BooleanType.yes.getCode());
        record.setReadtime(System.currentTimeMillis());
        int count = this.updateByExampleSelective(record, example);
        return count > 0;
    }

    @Override
    public int count(NewMsgQuery query) {
        NewmsgInboxExample example = buildExample(query);
        return this.countByExample(example);
    }

    private NewmsgInbox initEntity(NewMsgSendData sendData, NewMsgUser from, NewMsgUser to) {
        NewmsgInbox inboxApp = new NewmsgInbox();
        BeanUtils.copyProperties(sendData, inboxApp);
        inboxApp.setBody(null);
        inboxApp.setId(UUID(sendData.getMsgtype()));
        inboxApp.setCtime(System.currentTimeMillis());
        inboxApp.setState(BooleanType.yes.getCode());
        inboxApp.setUserread(BooleanType.no.getCode());
        inboxApp.setUserreply(BooleanType.no.getCode());
        if (to != null) {
            inboxApp.setUserid(to.getUserid());
            inboxApp.setDeptid(to.getDeptid());
        }

        if (from != null) {
            inboxApp.setFromUserid(from.getUserid());
            inboxApp.setFromDeptid(from.getDeptid());
        }

        if (!CollectionUtils.isEmpty(sendData.getExtMap())) {
            inboxApp.setExt(sendData.getExtMapJson());
        }

        if (!CollectionUtils.isEmpty(sendData.getParams())) {
            inboxApp.setParams(sendData.getParamsJson());
        }

        return inboxApp;
    }

    private static NewmsgInboxExample buildExample(NewMsgQuery query) {
        NewmsgInboxExample example = new NewmsgInboxExample();
        NewmsgInboxExample.Criteria criteria = example.createCriteria();
        if (query == null) {
            return example;
        }
        if (StringUtils.isNotBlank(query.getAppid())) {
            if (query.getAppid().contains(",")) {
                criteria.andAppidIn(Arrays.asList(query.getAppid().split(",")));
            } else {
                criteria.andAppidEqualTo(query.getAppid());
            }
        }

        if (StringUtils.isNotBlank(query.getAppname())) {
            criteria.andAppnameLike("%" + query.getAppname() + "%");
        }

        if (null != query.getMsgtype()) {
            criteria.andMsgtypeEqualTo(query.getMsgtype());
        }

        if (StringUtils.isNotBlank(query.getToUserid())) {
            criteria.andUseridEqualTo(query.getToUserid());
        }
        if (null != query.getToUsertype()) {
            criteria.andUsertypeEqualTo(query.getToUsertype());
        }
        if (StringUtils.isNotBlank(query.getToOrgid())) {
            criteria.andOrgidEqualTo(query.getToOrgid());
        }
        if (StringUtils.isNotBlank(query.getToDeptid())) {
            criteria.andDeptidEqualTo(query.getToDeptid());
        }

        if (StringUtils.isNotBlank(query.getFromUserid())) {
            criteria.andFromUseridEqualTo(query.getFromUserid());
        }
        if (null != query.getFromUsertype()) {
            criteria.andFromUsertypeEqualTo(query.getFromUsertype());
        }
        if (StringUtils.isNotBlank(query.getFromOrgid())) {
            criteria.andFromOrgidEqualTo(query.getFromOrgid());
        }
        if (StringUtils.isNotBlank(query.getFromDeptid())) {
            criteria.andFromDeptidEqualTo(query.getFromDeptid());
        }
        if (StringUtils.isNotBlank(query.getOutboxid())) {
            criteria.andOutboxidEqualTo(query.getOutboxid());
        }

        if (StringUtils.isNotBlank(query.getTitle())) {
            criteria.andTitleLike("%" + query.getTitle() + "%");
        }

        if (null != query.getUserread()) {
            criteria.andUserreadEqualTo(query.getUserread());
        }
        if (null != query.getUserreply()) {
            criteria.andUserreplyEqualTo(query.getUserreply());
        }

        if (null != query.getNeedreply()) {
            FormInboxExample4Json.OperateParam item = new FormInboxExample4Json.OperateParam();
            item.setFieldName("needreply");
            item.setFieldValue(query.getNeedreply());
            item.setOperate("eq");
            FormInboxExample4Json.addCriterion(criteria, item);
        }
        if (null != query.getHasatt()) {
            FormInboxExample4Json.OperateParam item = new FormInboxExample4Json.OperateParam();
            item.setFieldName("hasatt");
            item.setFieldValue("" + query.getHasatt());
            item.setOperate("eq");
            FormInboxExample4Json.addCriterion(criteria, item);
        }

        if (StringUtils.isNotBlank(query.getInboxid())) {
            criteria.andIdEqualTo(query.getInboxid());
        }

        if (!CollectionUtils.isEmpty(query.getInboxids())) {
            criteria.andIdIn(query.getInboxids());
        }

        if (!query.getAllState()) {
            if (!CollectionUtils.isEmpty(query.getStates())) {
                criteria.andStateIn(query.getStates());
            } else if (null != query.getState()) {
                criteria.andStateEqualTo(query.getState());
            } else {
                criteria.andStateEqualTo(BooleanType.yes.getCode());
            }
        }

        if (StringUtils.isNotBlank(query.getMsgcategory())) {
            FormInboxExample4Json.OperateParam item = new FormInboxExample4Json.OperateParam();
            item.setFieldName("msgcategory");
            item.setFieldValue(query.getMsgcategory());
            item.setOperate("eq");
            FormInboxExample4Json.addCriterion(criteria, item);
        }

        if (StringUtils.isNotBlank(query.getMsglevel())) {
            FormInboxExample4Json.OperateParam item = new FormInboxExample4Json.OperateParam();
            item.setFieldName("msglevel");
            item.setFieldValue(query.getMsglevel());
            item.setOperate("eq");
            FormInboxExample4Json.addCriterion(criteria, item);
        }

        if (null != query.getNullToOrgid()) {
            if (query.getNullToOrgid()) {
                criteria.andOrgidIsNull();
            } else {
                criteria.andOrgidIsNotNull();
            }
        }

        try {
            if (StringUtils.isNotBlank(query.getStarttime())) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = simpleDateFormat.parse(query.getStarttime() + " 00:00:00");
                criteria.andCtimeGreaterThanOrEqualTo(date.getTime());
            }

            if (StringUtils.isNotBlank(query.getEndtime())) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = simpleDateFormat.parse(query.getEndtime() + " 23:59:59");
                criteria.andCtimeLessThanOrEqualTo(date.getTime());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return example;
    }

    private String UUID(Byte msgType) {
        return msgType+"_" + UUID.randomUUID();
    }
}
