package com.bonus.material.basic.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONArray;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.enums.MessageTypeEnum;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.SpringUtils;
import com.bonus.common.redis.service.RedisService;
import com.bonus.common.security.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import com.bonus.material.basic.mapper.BmMessageMapper;
import com.bonus.material.basic.domain.BmMessage;
import com.bonus.material.basic.service.IBmMessageService;

import javax.annotation.Resource;

@Service
public class BmMessageServiceImpl implements IBmMessageService {
    @Resource
    private BmMessageMapper bmMessageMapper;

    @Resource
    private RedisService redisService;

    /**
     * 查询消息
     *
     * @param id 消息主键
     * @return 消息
     */
    @Override
    public BmMessage selectBmMessageById(Long id) {
        return bmMessageMapper.selectBmMessageById(id);
    }

    /**
     * 查询消息列表
     *
     * @param bmMessage 消息
     * @return 消息
     */
    @Override
    public List<BmMessage> selectBmMessageList(BmMessage bmMessage) {
        Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        bmMessage.setFromCompany(companyId);
        bmMessage.setToCompany(companyId);
        List<BmMessage> messages = bmMessageMapper.selectBmMessageList(bmMessage);
        List<BmMessage> mergedList = filterAndMerge(messages);
        return mergedList;
    }

    @Override
    public List<BmMessage> selectBmMessageListOne(BmMessage bmMessage) {
        Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        bmMessage.setFromCompany(bmMessage.getFromCompany());
        bmMessage.setToCompany(companyId);
        List<BmMessage> messages = bmMessageMapper.selectBmMessageListOne(bmMessage);
        return messages;
    }

    @Override
    public List<BmMessage> selectBmMessageListFromCache(BmMessage bmMessage) {
        Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        RedisService redisService = SpringUtils.getBean(RedisService.class);

        // 获取所有消息缓存 key
        Collection<String> keys = redisService.keys(MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + "*");
        if (keys == null || keys.isEmpty()) {
            return new ArrayList<>();
        }

        List<BmMessage> list = new ArrayList<>();

        // 遍历 key 获取消息列表
        for (String key : keys) {
            JSONArray arrayCache = redisService.getCacheObject(key);
            if (arrayCache != null && !arrayCache.isEmpty()) {
                try {
                    list.addAll(arrayCache.toList(BmMessage.class));
                } catch (Exception e) {
                    // 可记录日志：log.warn("解析缓存失败，key={}", key, e);
                }
            }
        }

        // 过滤当前公司相关消息并排序
        List<BmMessage> filteredList = list.stream()
                .filter(o -> companyId.equals(o.getFromCompany()) || companyId.equals(o.getToCompany()))
                .sorted(Comparator.comparing(BmMessage::getCreateTime))
                .collect(Collectors.toList());

        // 合并消息
        List<BmMessage> mergedList = filterAndMerge(filteredList);

        return mergedList;
    }

    @Override
    public List<BmMessage> selectBmMessageListFromCacheOne(BmMessage bmMessage) {
        Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        Long toCompany = bmMessage.getToCompany();

        RedisService redisService = SpringUtils.getBean(RedisService.class);

        String keyPattern1 = MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + toCompany + ":" + companyId;
        String keyPattern2 = MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + companyId + ":" + toCompany;

        Collection<String> keys1 = redisService.keys(keyPattern1);
        Collection<String> keys2 = redisService.keys(keyPattern2);

        List<String> keys = new ArrayList<>();
        if (keys1 != null) {
            keys.addAll(keys1);
        }
        if (keys2 != null) {
            keys.addAll(keys2);
        }

        List<BmMessage> list = new ArrayList<>();

        for (String key : keys) {
            JSONArray arrayCache = redisService.getCacheObject(key);
            if (arrayCache != null && !arrayCache.isEmpty()) {
                try {
                    list.addAll(arrayCache.toList(BmMessage.class));
                } catch (Exception e) {
                    // 可记录日志或跳过异常条目
                    // log.warn("Failed to parse BmMessage from cache key: {}", key, e);
                }
            }
        }

        return list.stream()
                .sorted(Comparator.comparing(BmMessage::getCreateTime))
                .collect(Collectors.toList());
    }






    /**
     * 根据所属公司查询消息未读数量
     * @param bmMessage
     * @return
     */
    @Override
    public BmMessage getNoReadNum(BmMessage bmMessage) {
        bmMessage.setToCompany(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()));
        return bmMessageMapper.getNoReadNum(bmMessage);
    }

    /**
     * 新增消息
     *
     * @param bmMessage 消息
     * @return 结果
     */
    @Override
    public int insertBmMessage(BmMessage bmMessage) {
        bmMessage.setCreateTime(DateUtils.getNowDate());
        try {
            Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                    .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
            bmMessage.setFromCompany(companyId);
            bmMessage.setFromUser(SecurityUtils.getLoginUser().getSysUser().getUserId());
            bmMessage.setUuid(String.valueOf(UUID.randomUUID()));
            bmMessage.setMessageType(String.valueOf(MessageTypeEnum.CHAT_MESSAGE.getType()));
            bmMessage.setIsRead(0);
            String msgKey = MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + companyId + ":" + bmMessage.getToCompany();
            JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(msgKey);
            if (arrayCache == null) {
                arrayCache = new JSONArray();
            }
            List<BmMessage> list = arrayCache.toList(BmMessage.class);
            list.add(bmMessage);
            (SpringUtils.getBean(RedisService.class)).deleteObject(msgKey);
            (SpringUtils.getBean(RedisService.class)).setCacheObject(msgKey, list, MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE_HOURS, TimeUnit.HOURS);
            return bmMessageMapper.insertBmMessage(bmMessage);
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
    }

    /**
     * 修改消息
     *
     * @param bmMessage 消息
     * @return 结果
     */
    @Override
    public int updateBmMessage(BmMessage bmMessage) {
        bmMessage.setIsRead(1);
        bmMessage.setUpdateTime(DateUtils.getNowDate());
        try {
            bmMessageMapper.updateBmMessage(bmMessage);
            //Redis
            Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                    .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
            Collection<String> keys1 = SpringUtils.getBean(RedisService.class).keys(MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + bmMessage.getFromCompany() + ":" + companyId);
            Collection<String> keys2 = SpringUtils.getBean(RedisService.class).keys(MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + companyId + ":" + bmMessage.getToCompany());
            List<String> keys = new ArrayList<>();
            keys.addAll(keys1);
            keys.addAll(keys2);
            for (String key : keys) {
                JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(key);
                List<BmMessage> list = arrayCache.toList(BmMessage.class);
                list.stream().forEach(t -> t.setIsRead(1));
                SpringUtils.getBean(RedisService.class).setCacheObject(key, list);
            }
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
        return 1;
    }

    @Override
    public int updateBmMessageAll(BmMessage bmMessage) {
        bmMessage.setIsRead(1);
        bmMessage.setUpdateTime(DateUtils.getNowDate());
        Long companyId = Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId())
                .orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        bmMessage.setToCompany(companyId);
        for (Long fromCompany : bmMessage.getFromCompanys()) {
            try {
                bmMessage.setFromCompany(fromCompany);
                bmMessageMapper.updateBmMessage(bmMessage);
                //Redis
                Collection<String> keys1 = SpringUtils.getBean(RedisService.class).keys(MaterialConstants.CACHE_MATERIAL_MALL_MESSAGE + fromCompany + ":" + companyId);
                List<String> keys = new ArrayList<>();
                keys.addAll(keys1);
                for (String key : keys) {
                    JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(key);
                    List<BmMessage> list = arrayCache.toList(BmMessage.class);
                    list.stream().forEach(t -> t.setIsRead(1));
                    SpringUtils.getBean(RedisService.class).setCacheObject(key, list);
                }
            } catch (Exception e) {
                throw new ServiceException("错误信息描述");
            }
        }
        return 1;
    }

    /**
     * 批量删除消息
     *
     * @param ids 需要删除的消息主键
     * @return 结果
     */
    @Override
    public int deleteBmMessageByIds(Long[] ids) {
        return bmMessageMapper.deleteBmMessageByIds(ids);
    }

    /**
     * 删除消息信息
     *
     * @param id 消息主键
     * @return 结果
     */
    @Override
    public int deleteBmMessageById(Long id) {
        return bmMessageMapper.deleteBmMessageById(id);
    }


    /*public static List<BmMessage> filterAndMerge(List<BmMessage> sortedList) {

        Map<String, BmMessage> matchingPairs = new HashMap<>();

        List<BmMessage> mergedList = new ArrayList<>();

        for (BmMessage message : sortedList) {
            String forwardKey = message.getFromCompany() + "-" + message.getToCompany();
            String reverseKey = message.getToCompany() + "-" + message.getFromCompany();

            if (matchingPairs.containsKey(forwardKey) || matchingPairs.containsKey(reverseKey)) {
                matchingPairs.remove(forwardKey);
                matchingPairs.remove(reverseKey);
                    for (BmMessage bmMessage : mergedList) {
                        if ((bmMessage.getFromCompany().equals(message.getFromCompany()) || bmMessage.getFromCompany().equals(message.getToCompany())) && bmMessage.getToCompany().equals(message.getToCompany()) || bmMessage.getToCompany().equals(message.getFromCompany())) {
                            mergedList.remove(bmMessage);
                            mergedList.add(message);
                        }
                    }
            } else {
                matchingPairs.put(forwardKey, message);
                matchingPairs.put(reverseKey, message);
                mergedList.add(message);
            }
        }
        return mergedList;
    }*/
    public static List<BmMessage> filterAndMerge(List<BmMessage> sortedList) {

        Map<String, BmMessage> matchingPairs = new HashMap<>();
        List<BmMessage> mergedList = new ArrayList<>();
        Set<String> processedPairs = new HashSet<>();

        for (BmMessage message : sortedList) {
            if (message == null || message.getFromCompany() == null || message.getToCompany() == null) {
                continue; // 跳过无效消息
            }

            String forwardKey = message.getFromCompany() + "-" + message.getToCompany();
            String reverseKey = message.getToCompany() + "-" + message.getFromCompany();

            if (matchingPairs.containsKey(forwardKey) || matchingPairs.containsKey(reverseKey)) {

                // 使用 Iterator 遍历并移除匹配的消息
                Iterator<BmMessage> iterator = mergedList.iterator();
                while (iterator.hasNext()) {
                    BmMessage bmMessage = iterator.next();
                    if (bmMessage.getFromCompany().equals(message.getFromCompany()) && bmMessage.getToCompany().equals(message.getToCompany()) ||
                            bmMessage.getFromCompany().equals(message.getToCompany()) && bmMessage.getToCompany().equals(message.getFromCompany())) {
                        iterator.remove();
                        BmMessage bmMessage1 = matchingPairs.get(forwardKey);
                        BmMessage bmMessage2 = matchingPairs.get(reverseKey);
                        if (bmMessage1 != null && bmMessage2 == null){
                            message.setFromCompany(bmMessage1.getFromCompany());
                            message.setFromCompanyName(bmMessage1.getFromCompanyName());
                            message.setFromUser(bmMessage1.getFromUser());
                            message.setToCompany(bmMessage1.getToCompany());
                            message.setToCompanyName(bmMessage1.getToCompanyName());
                            message.setToUser(bmMessage1.getToUser());
                        }
                        if (bmMessage1 == null && bmMessage2 != null){
                            message.setFromCompany(bmMessage2.getFromCompany());
                            message.setFromCompanyName(bmMessage2.getFromCompanyName());
                            message.setFromUser(bmMessage2.getFromUser());
                            message.setToCompany(bmMessage2.getToCompany());
                            message.setToCompanyName(bmMessage2.getToCompanyName());
                            message.setToUser(bmMessage2.getToUser());
                        }
                        if (bmMessage1 != null && bmMessage2 != null){
                            if (bmMessage1.getCreateTime().before(bmMessage2.getCreateTime())){
                                message.setFromCompany(bmMessage1.getFromCompany());
                                message.setFromCompanyName(bmMessage1.getFromCompanyName());
                                message.setFromUser(bmMessage1.getFromUser());
                                message.setToCompany(bmMessage1.getToCompany());
                                message.setToCompanyName(bmMessage1.getToCompanyName());
                                message.setToUser(bmMessage1.getToUser());
                            }else {
                                message.setFromCompany(bmMessage2.getFromCompany());
                                message.setFromCompanyName(bmMessage2.getFromCompanyName());
                                message.setFromUser(bmMessage2.getFromUser());
                                message.setToCompany(bmMessage2.getToCompany());
                                message.setToCompanyName(bmMessage2.getToCompanyName());
                                message.setToUser(bmMessage2.getToUser());
                            }
                        }
                        mergedList.add(message);
                        break;
                    }
                }
            } else {
                // 添加新的匹配项
                if (!processedPairs.contains(forwardKey) && !processedPairs.contains(reverseKey)) {
                    matchingPairs.put(forwardKey, message);
                    matchingPairs.put(reverseKey, message);
                    mergedList.add(message);
                    processedPairs.add(forwardKey);
                    processedPairs.add(reverseKey);
                }
            }
        }
        return mergedList;
    }
}
