package com.fjhx.mail.service.message.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.customer.entity.customer.po.CustomerUser;
import com.fjhx.customer.entity.customer.vo.CustomerVo;
import com.fjhx.customer.service.customer.CustomerService;
import com.fjhx.customer.service.customer.CustomerUserService;
import com.fjhx.mail.config.MailServiceConfig;
import com.fjhx.mail.entity.dto.GetMessagePageDto;
import com.fjhx.mail.entity.enterprise.po.EnterpriseDomain;
import com.fjhx.mail.entity.enterprise.po.EnterpriseFolder;
import com.fjhx.mail.entity.enterprise.po.EnterpriseMailbox;
import com.fjhx.mail.entity.enterprise.po.EnterpriseMessage;
import com.fjhx.mail.entity.message.dto.DeleteBatchMailDto;
import com.fjhx.mail.entity.message.dto.DeleteMailDto;
import com.fjhx.mail.entity.message.dto.SendDto;
import com.fjhx.mail.entity.message.dto.SetSeenDto;
import com.fjhx.mail.entity.my.vo.MessageVo;
import com.fjhx.mail.entity.personal.po.PersonalFolder;
import com.fjhx.mail.entity.personal.po.PersonalMailbox;
import com.fjhx.mail.entity.personal.po.PersonalMessage;
import com.fjhx.mail.mapper.enterprise.EnterpriseMessageMapper;
import com.fjhx.mail.mapper.message.MessageAttachmentMapper;
import com.fjhx.mail.mapper.personal.PersonalMessageMapper;
import com.fjhx.mail.service.enterprise.EnterpriseDomainService;
import com.fjhx.mail.service.enterprise.EnterpriseFolderService;
import com.fjhx.mail.service.enterprise.EnterpriseMailboxService;
import com.fjhx.mail.service.enterprise.EnterpriseMessageService;
import com.fjhx.mail.service.message.InfoService;
import com.fjhx.mail.service.personal.PersonalFolderService;
import com.fjhx.mail.service.personal.PersonalMailboxService;
import com.fjhx.mail.service.personal.PersonalMessageService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class InfoServiceImpl implements InfoService {

    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private PersonalMailboxService personalMailboxService;

    @Autowired
    private EnterpriseMailboxService enterpriseMailboxService;

    @Autowired
    private EnterpriseDomainService enterpriseDomainService;

    @Autowired
    private EnterpriseMessageService enterpriseMessageService;

    @Autowired
    private PersonalMessageService personalMessageService;

    @Autowired
    private PersonalFolderService personalFolderService;
    @Autowired
    private EnterpriseFolderService enterpriseFolderService;

    @Autowired
    private EnterpriseMessageMapper enterpriseMessageMapper;
    @Autowired
    private PersonalMessageMapper personalMessageMapper;
    @Autowired
    private CustomerService customerService;
    @Autowired
    private CustomerUserService customerUserService;

    @Autowired
    private MessageAttachmentMapper messageAttachmentMapper;

    @Override
    public List<SysUser> getUserList() {

        DynamicDataSourceContextHolder.push(SourceConstant.BASE);

        Long userId = SecurityUtils.getUserId();

        List<SysDept> sysDeptList = sysDeptService.list(Wrappers.<SysDept>lambdaQuery()
                .and(q -> q.eq(SysDept::getDirectorId, userId).or().eq(SysDept::getLeaderId, userId)));

        if (sysDeptList.size() == 0) {
            return new ArrayList<>();
        }

        Set<Long> deptSet = new HashSet<>();
        List<SysDept> list = sysDeptService.list();
        Map<Long, List<SysDept>> parentDeptMap = list.stream().collect(Collectors.groupingBy(SysDept::getParentId));

        for (SysDept sysDept : sysDeptList) {
            Long deptId = sysDept.getDeptId();

            if (Objects.equals(sysDept.getDirectorId(), userId)) {
                subordinateDeptId(deptId, deptSet, parentDeptMap);
            } else {
                deptSet.add(deptId);
            }
        }

        List<SysUser> sysUserList = sysUserService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getDeptId, deptSet));
        sysUserList.forEach(item -> item.setPassword(null));

        DynamicDataSourceContextHolder.poll();
        return sysUserList;
    }

    @Override
    public String sendMail(SendDto dto) {
        String sendMail = getUrl("sendMail", dto.getType(), dto.getMailboxId());
        return HttpUtil.post(sendMail, JSON.toJSONString(dto));
    }

    @Override
    public void deleteMail(DeleteMailDto dto) {
        if (dto.getType().equals(1)) {
            personalMessageService.removeById(dto.getId());
        } else {
            enterpriseMessageService.removeById(dto.getId());
        }
    }

    @Override
    public List<SysUser> getExistMailUserList() {
        List<SysUser> userList = getUserList();

        if (userList.size() == 0) {
            return userList;
        }

        List<Long> userIdList = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());

        List<Long> existMailUserIdList = new ArrayList<>();

        List<Long> enterpriseUserId = enterpriseMailboxService.listObject(EnterpriseMailbox::getUserId,
                q -> q.in(EnterpriseMailbox::getUserId, userIdList));

        List<Long> personalUserId = personalMailboxService.listObject(PersonalMailbox::getUserId,
                q -> q.in(PersonalMailbox::getUserId, userIdList));

        existMailUserIdList.addAll(enterpriseUserId);
        existMailUserIdList.addAll(personalUserId);

        return userList.stream()
                .filter(item -> existMailUserIdList.contains(item.getUserId()))
                .collect(Collectors.toList());

    }

    @Override
    public void deleteBatchMail(DeleteBatchMailDto dto) {
        if (dto.getType().equals(1)) {
            personalMessageService.removeBatchByIds(dto.getIdList());
        } else {
            enterpriseMessageService.removeBatchByIds(dto.getIdList());
        }
    }

    @Override
    public JSONObject setSeen(SetSeenDto dto) {
        String url = getUrl("setSeen", dto.getType(), dto.getMailboxId());
        String post = HttpUtil.post(url, JSON.toJSONString(dto));
        return JSONObject.parseObject(post);
    }

    @Override
    public JSONObject cancelSeen(SetSeenDto dto) {
        String url = getUrl("cancelSeen", dto.getType(), dto.getMailboxId());
        String post = HttpUtil.post(url, JSON.toJSONString(dto));
        return JSONObject.parseObject(post);
    }

    private void subordinateDeptId(Long deptId, Set<Long> deptSet, Map<Long, List<SysDept>> parentDeptMap) {
        deptSet.add(deptId);

        // 获取子部门
        List<SysDept> sysDeptList = parentDeptMap.get(deptId);
        if (ObjectUtil.isEmpty(sysDeptList)) {
            return;
        }

        for (SysDept sysDept : sysDeptList) {
            subordinateDeptId(sysDept.getDeptId(), deptSet, parentDeptMap);
        }

    }

    private String getUrl(String prefix, Integer type, Long mailboxId) {
        String urlPrefix;

        StringJoiner urlJoiner = new StringJoiner("/");
        urlJoiner.add(prefix);

        if (type == 1) {
            PersonalMailbox personalMailbox = personalMailboxService.getById(mailboxId);
            if (personalMailbox == null) {
                throw new ServiceException("未找到个人邮箱");
            }

            urlJoiner.add(personalMailbox.getSendHost());
            urlJoiner.add(personalMailbox.getMailUser());
            urlJoiner.add(personalMailbox.getMailPassword());

            if (Objects.equals(personalMailbox.getType(), 2)) {
                urlPrefix = MailServiceConfig.abroadUrlPrefix;
            } else {
                urlPrefix = MailServiceConfig.urlPrefix;
            }
        } else {
            EnterpriseMailbox enterpriseMailbox = enterpriseMailboxService.getById(mailboxId);
            if (enterpriseMailbox == null) {
                throw new ServiceException("未找到企业邮箱");
            }
            EnterpriseDomain enterpriseDomain = enterpriseDomainService.getById(enterpriseMailbox.getDomainId());
            if (enterpriseDomain == null) {
                throw new ServiceException("未找到企业邮箱配置");
            }
            urlJoiner.add(enterpriseDomain.getSendHost());
            urlJoiner.add(enterpriseMailbox.getMailUserPrefix() + "@" + enterpriseDomain.getDomainName());
            urlJoiner.add(enterpriseMailbox.getMailPassword());

            if (Objects.equals(enterpriseDomain.getType(), 2)) {
                urlPrefix = MailServiceConfig.abroadUrlPrefix;
            } else {
                urlPrefix = MailServiceConfig.urlPrefix;
            }
        }

        return urlPrefix + urlJoiner;
    }


    @Override
    public Object getMessagePage(GetMessagePageDto dto) {
        String keyword = dto.getKeyword();

        Page<MessageVo> page;

        // 个人邮箱
        if (dto.getType().equals(1)) {
            QueryWrapper<PersonalMessage> wrapper = Wrappers.query();
            wrapper.eq(ObjectUtil.isNotEmpty(dto.getMailboxId()), "pm.mailbox_id", dto.getMailboxId());

            //往来邮件
            if (ObjectUtil.isNotEmpty(dto.getDealingsEmail())) {
                wrapper.and(q1 -> q1
                        .eq("pm.from_email", dto.getDealingsEmail())
                        .or().apply("FIND_IN_SET('" + dto.getDealingsEmail() + "', pm.recipients)")
                );
            }

            wrapper.eq(ObjectUtil.isNotEmpty(dto.getFolderId()), "pm.folder_id", dto.getFolderId());
            wrapper.and(ObjectUtil.isNotEmpty(keyword), q1 -> q1
                            .like("pm.from_email", keyword)
                            .or().like("pm.subject", keyword)
//                    .or().like("pmc.content", keyword)
//                    .or().like("c.name", keyword)
//                    .or().like("cu.name", keyword)
                            .or().like("pm.from_personal_name", keyword)
            );
            wrapper.orderByDesc("pm.send_date");
            page = personalMessageMapper.getPage(dto.getPage(), wrapper, SecurityUtils.getTenantId());

            if (page.getSize() == 0) {
                return page;
            }

            if (ObjectUtil.isNotEmpty(dto.getFolderId())) {
                PersonalFolder personalFolder = personalFolderService.getById(dto.getFolderId());
                if (personalFolder == null) {
                    throw new ServiceException("文件夹已被删除");
                }
            }

        }
        // 企业邮箱
        else {
            QueryWrapper<EnterpriseMessage> wrapper = Wrappers.query();
            wrapper.eq(ObjectUtil.isNotEmpty(dto.getMailboxId()), "em.mailbox_id", dto.getMailboxId());

            wrapper.eq(ObjectUtil.isNotEmpty(dto.getFolderId()), "em.folder_id", dto.getFolderId());

            if (ObjectUtil.isNotEmpty(keyword)) {

                wrapper.and(ObjectUtil.isNotEmpty(dto.getKeyword()), q1 -> q1
                                .like("em.from_email", dto.getKeyword())
                                .or().like("em.subject", dto.getKeyword())
//                    .or().like("emc.content", dto.getKeyword())
//                    .or().like("c.name", dto.getKeyword())
//                    .or().like("cu.name", dto.getKeyword())
                                .or().like("em.from_personal_name", dto.getKeyword())
//                    .or().apply("em.id in (select message_id from enterprise_message_content where content like CONCAT('%','" + keyword + "','%'))")
                );
            }
            wrapper.orderByDesc("em.send_date");
            page = enterpriseMessageMapper
                    .getPage(dto.getPage(), wrapper, SecurityUtils.getTenantId(), keyword);

            if (page.getSize() == 0) {
                return page;
            }

            if (ObjectUtil.isNotEmpty(dto.getFolderId())) {
                EnterpriseFolder enterpriseFolder = enterpriseFolderService.getById(dto.getFolderId());
                if (enterpriseFolder == null) {
                    throw new ServiceException("文件夹已被删除");
                }
            }
        }

        List<MessageVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return R.ok(page);
        }
        List<Long> messageIds = records.stream().map(MessageVo::getId).collect(Collectors.toList());

//        //赋值邮件附件信息
//        List<MessageAttachment> messageAttachmentList = messageAttachmentMapper.getList(Wrappers.query().in("ma.message_id", messageIds), dto.getType());
//        String obsUrl = SpringUtil.getProperty("obs.url");
//        messageAttachmentList.forEach(item -> item.setUrl(obsUrl + item.getUrl()));
//
//        Map<Long, List<MessageAttachment>> MessageAttachmentMap = messageAttachmentList.stream().collect(Collectors.groupingBy(MessageAttachment::getMessageId));
//        for (MessageVo record : records) {
//            List<MessageAttachment> messageAttachments = MessageAttachmentMap.get(record.getId());
//            record.setMessageAttachmentList(messageAttachmentList);
//        }


        //赋值客户信息
        List<String> eMailList = records.stream().map(MessageVo::getFromEmail).distinct().collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(eMailList)) {
            List<CustomerUser> customerUserList = customerUserService.list(q -> q.in(CustomerUser::getEmail, eMailList));
            if (ObjectUtil.isEmpty(customerUserList)) {
                return R.ok(page);
            }
            List<Long> customerIds = customerUserList.stream().map(CustomerUser::getCustomerId).collect(Collectors.toList());

            //赋值客户信息
            List<CustomerVo> customerInfoByIds = customerService.getCustomerInfoByIds(customerIds);
            Map<String, CustomerUser> customerUserMap = customerUserList.stream().collect(Collectors.toMap(CustomerUser::getEmail, Function.identity()));
            Map<Long, CustomerVo> customerInfoMap = customerInfoByIds.stream().collect(Collectors.toMap(CustomerVo::getId, Function.identity()));
            for (MessageVo record : records) {
                CustomerUser customerUser = customerUserMap.get(record.getFromEmail());
                if (ObjectUtil.isEmpty(customerUser)) {
                    continue;
                }
                Long customerId = customerUser.getCustomerId();
                record.setCustomerId(customerId);
                record.setCustomerInfo(customerInfoMap.get(customerId));
            }
        }

        return R.ok(page);
    }

}
