package com.gic.haoban.manage.service.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.JSONResponse;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.commons.util.GICMQClientUtil;
import com.gic.dubbo.entity.ProviderLocalTag;
import com.gic.enterprise.api.dto.QRcodeDTO;
import com.gic.enterprise.api.service.ImageService;
import com.gic.haoban.manage.api.constants.Manage3Constants;
import com.gic.haoban.manage.api.dto.QwFrientNoticeDTO;
import com.gic.haoban.manage.api.dto.QywxErrorLogDTO;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.dto.hm.HmClerkRelationDTO;
import com.gic.haoban.manage.api.dto.hm.HmQrcodeDTO;
import com.gic.haoban.manage.api.enums.WelcomeMediaTypeEnum;
import com.gic.haoban.manage.api.enums.hm.HmWelcomeReferType;
import com.gic.haoban.manage.api.service.hm.HmClerkRelationApiService;
import com.gic.haoban.manage.api.service.hm.HmQrcodeApiService;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
import com.gic.haoban.manage.service.entity.TabHaobanClerkMainStoreRelated;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.entity.TabHaobanWxEnterprise;
import com.gic.haoban.manage.service.entity.TabMiniprogramSetting;
import com.gic.haoban.manage.service.pojo.bo.hm.KeyDataLinkBO;
import com.gic.haoban.manage.service.pojo.bo.welcome.WelcomeDetailBO;
import com.gic.haoban.manage.service.pojo.bo.welcome.WelcomeMediaBO;
import com.gic.haoban.manage.service.pojo.bo.welcome.WelcomeReferBO;
import com.gic.haoban.manage.service.service.ClerkMainStoreRelatedService;
import com.gic.haoban.manage.service.service.KeyDataService;
import com.gic.haoban.manage.service.service.MiniprogramSettingService;
import com.gic.haoban.manage.service.service.StaffClerkRelationService;
import com.gic.haoban.manage.service.service.WelcomeSendService;
import com.gic.haoban.manage.service.service.WelcomeService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.util.CommonUtil;
import com.gic.haoban.manage.service.util.EmojiFilterUtil;
import com.gic.mq.sdk.GicMQClient;
import com.gic.wechat.api.dto.qywx.welcome.QywxExternalMessageBaseDTO;
import com.gic.wechat.api.dto.qywx.welcome.QywxFileExternalBaseDTO;
import com.gic.wechat.api.dto.qywx.welcome.QywxImageExternalBaseDTO;
import com.gic.wechat.api.dto.qywx.welcome.QywxLinkExternalBaseDTO;
import com.gic.wechat.api.dto.qywx.welcome.QywxMiniprogramExternalBaseDTO;
import com.gic.wechat.api.dto.qywx.welcome.QywxVideoExternalBaseDTO;
import com.gic.wechat.api.dto.qywx.welcome.QywxWelcomeMsgDTO;
import com.gic.wechat.api.enums.QywxMediaTypeEnum;
import com.gic.wechat.api.service.qywx.QywxSuiteApiService;
import com.gic.wechat.api.service.qywx.QywxUserApiService;

import cn.hutool.core.convert.Convert;
import cn.hutool.crypto.SecureUtil;

@Service
public class WelcomeSendServiceImpl implements WelcomeSendService {

    private static final Logger log = LogManager.getLogger(WelcomeSendServiceImpl.class);
    @Autowired
    private QywxUserApiService qywxUserApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private ClerkService clerkService;
    @Autowired
    private ClerkMainStoreRelatedService clerkMainStoreRelatedService;
    @Autowired
    private Config config;
    @Autowired
    private QywxSuiteApiService qywxSuiteApiService;
    @Autowired
    private StaffClerkRelationService staffClerkRelationService;
    @Autowired
    private MiniprogramSettingService miniprogramSettingService;
    @Autowired
    private WelcomeService welcomeService;
    @Autowired
    private ImageService imageService;
    @Autowired
    private HmQrcodeApiService hmQrcodeApiService;
    @Autowired
    private KeyDataService keyDataService;
    @Autowired
    private HmClerkRelationApiService hmClerkRelationApiService;
    @Autowired
    private StaffMapper staffMapper;

    private static GicMQClient clientInstance = GICMQClientUtil.getClientInstance();

    @Override
    public void sendWelcome(String params) {
        log.info("发送欢迎语={}", params);
        QwFrientNoticeDTO dto = JSON.parseObject(params, QwFrientNoticeDTO.class);
        this.sendWelcome(dto.getCorpid(), dto.getExternalUserid(), dto.getWelcomeCode(), dto.getWxUserId(),
                dto.getState());
    }

    /**
     * 发送欢迎语
     *
     * @param dto
     * @param wxEnterpriseDTO
     * @param enterpriseId
     * @param staffId
     * {"data":{"welcomeCode":"J0GjdrsF-nZNac3Xc6V2K2p8OokQZcY4g0jxljdHc7A","wxUserId":"016903","suiteid":"selfSuiteId","corpid":"wxbde984c3488b837e","externalUserid":"wmSe9FEAAAy39F1NI6Z-THUUd9mkqOIw","changeType":"add_external_contact"},"type":1,"mqTraceId":"278473818-1-1679557069.126"}
     */
    @Override
    public void sendWelcome(String corpid, String externalUserId, String welcomeCode, String wxUserId, String state) {
        if (StringUtils.isEmpty(welcomeCode)) {
            log.error("welcomeCode为空,externalUserId={}", externalUserId);
            return;
        }
        TabHaobanWxEnterprise wxEnterprise = this.wxEnterpriseService.getEnterpriseBycorpId(corpid);
        if (wxEnterprise == null) {
            log.info("企业不存在,corpid={}", corpid);
            return;
        }
        String wxEnterpriseId = wxEnterprise.getWxEnterpriseId();
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (qwDTO == null) {
            log.info("企业不存在,wxEnterpriseId={}", wxEnterpriseId);
            return;
        }
        TabHaobanStaff staff = this.staffMapper.selectByUserIdAndEnterpriseId(wxUserId, wxEnterpriseId);
        if (null == staff) {
            log.info("成员不存在,wxUserid={}", wxUserId);
            return;
        }
        String staffId = staff.getStaffId();
        log.info("发送欢迎语,state={}", state);
        String relationKey = SecureUtil.md5(staffId + externalUserId);
        WelcomeDetailBO welcomeBO = null;
        if (StringUtils.isNotBlank(state)
                && (state.startsWith(Manage3Constants.HM) || state.startsWith(Manage3Constants.DT))) {
            WelcomeReferBO welcomeReferBo = getWelcomeReferBo(state);
            welcomeBO = welcomeService.getMatchWelcomeWithReferId(staffId, wxEnterpriseId, welcomeReferBo);
        } else {
            welcomeBO = welcomeService.getMatchWelcome(staffId, wxEnterpriseId);
        }
        if (Objects.isNull(welcomeBO)) {
            log.info("欢迎语未配置wxEnterpriseId:{}", wxEnterpriseId);
            return;
        }
        // 内容
        log.info("欢迎语发送{}={}", welcomeBO.getWelcomeId(), JSON.toJSONString(welcomeBO));
        String content = welcomeBO.getWelcomeContent();
        if (content.contains("<微信昵称>")) {
            String nickName = this.getExternalUserName(qwDTO, externalUserId);
            content = content.replaceAll("<微信昵称>", nickName);
        }
        QywxWelcomeMsgDTO qywxWelcomeMsgDTO = new QywxWelcomeMsgDTO();
        // 欢迎语内容
        qywxWelcomeMsgDTO.setText(content);
        // 欢迎语类型
        List<QywxExternalMessageBaseDTO> attachments = new ArrayList<>();
        // 开始设置欢迎语附件
        List<WelcomeMediaBO> mediaList = welcomeBO.getWelcomeMediaList();
        mediaList.forEach(one -> {
            Integer mediaType = one.getMediaType();
            if (WelcomeMediaTypeEnum.IMAGE.getCode().equals(mediaType)) {
                attachmentAddImage(attachments, one, corpid);
            }
            if (WelcomeMediaTypeEnum.VIDEO.getCode().equals(mediaType)) {
                attachmentAddVideo(attachments, one, corpid);
            }
            if (WelcomeMediaTypeEnum.FILE.getCode().equals(mediaType)) {
                attachmentAddFile(attachments, one, corpid);
            }
            if (WelcomeMediaTypeEnum.LINK.getCode().equals(mediaType)) {
                attachmentAddLink(attachments, one);
            }
            if (WelcomeMediaTypeEnum.PROGRAM.getCode().equals(mediaType)) {
                attachmentAddProgram(attachments, one, wxEnterpriseId);
            }
            if (WelcomeMediaTypeEnum.PARAM_PROGRAM.getCode().equals(mediaType)
                    || WelcomeMediaTypeEnum.PARAM_QRCODE.getCode().equals(mediaType)) {
                String clerkId = this.getClerkId(wxEnterpriseId, staffId, state);
                String enterpriseId = null;
                if (null != clerkId) {
                    ClerkDTO clerk = this.clerkService.getclerkById(clerkId);
                    if (null != clerk) {
                        enterpriseId = clerk.getEnterpriseId();
                    }
                }
                if (WelcomeMediaTypeEnum.PARAM_QRCODE.getCode().equals(mediaType)) {
                    attachmentAddParamQrCode(attachments, enterpriseId, clerkId, corpid, relationKey);
                }
                if (WelcomeMediaTypeEnum.PARAM_PROGRAM.getCode().equals(mediaType)) {
                    attachmentAddParamProgram(attachments, enterpriseId, wxEnterpriseId, relationKey);
                }
            }
        });
        if (CollectionUtils.isNotEmpty(attachments)) {
            qywxWelcomeMsgDTO.setAttachments(attachments);
        }
        qywxWelcomeMsgDTO.setWelcomeCode(welcomeCode);
        String result = this.qywxUserApiService.sendWelcomeMsgByExternal(corpid, config.getWxSuiteid(),
                qywxWelcomeMsgDTO);
        log.info("发送欢迎语 params:{},返回={}", JSON.toJSONString(qywxWelcomeMsgDTO), result);
        if (StringUtils.isNotBlank(result)) {
            JSONObject json = JSON.parseObject(result);
            int errcode = json.getIntValue("errcode");
            if (0 != errcode) {
                try {
                    QywxErrorLogDTO errLog = new QywxErrorLogDTO();
                    errLog.setWxEnterpriseId(wxEnterpriseId);
                    errLog.setExternalUserId(externalUserId);
                    errLog.setTraceId(ProviderLocalTag.tag.get().traceId);
                    errLog.setQywxErrorType(1);
                    errLog.setScenario("欢迎语");
                    errLog.setErrorContent(result);
                    clientInstance.sendMessage(Manage3Constants.QYWX_ERROR_MSG, JSON.toJSONString(errLog));
                } catch (Exception e) {
                    log.error("发送消息失败：{}", e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 获取链接或者活码id
     */
    private WelcomeReferBO getWelcomeReferBo(String state) {
        WelcomeReferBO welcomeReferBo = new WelcomeReferBO();
        String id = state.substring(2);
        if (state.contains(Manage3Constants.HM)) {
            welcomeReferBo.setType(HmWelcomeReferType.HM.getCode());
            welcomeReferBo.setReferId(id);
        } else if (state.contains(Manage3Constants.DT)) {
            KeyDataLinkBO dataForHmLink = keyDataService.getDataForHmLink(id);
            if (dataForHmLink != null) {
                welcomeReferBo.setType(HmWelcomeReferType.LINK.getCode());
                welcomeReferBo.setReferId(Convert.toStr(dataForHmLink.getLinkId()));
            }
        }
        return welcomeReferBo;
    }

    private void attachmentAddImage(List<QywxExternalMessageBaseDTO> attachments, WelcomeMediaBO media, String corpid) {
        String mediaUrl = media.getMediaUrl();
        String[] arr = mediaUrl.split("/");
        JSONResponse jp = qywxSuiteApiService.uploadMedia(corpid, config.getWxSuiteid(),
                CommonUtil.getFileByte(mediaUrl), arr[arr.length - 1], QywxMediaTypeEnum.IMAGE.getCode());
        log.info("欢迎语发送图片返回：{}", JSON.toJSONString(jp));
        if (jp.getErrorCode() == 0) {
            QywxImageExternalBaseDTO qywxImageExternalBaseDTO = new QywxImageExternalBaseDTO();
            qywxImageExternalBaseDTO.setMediaId(jp.getResult().toString());
            attachments.add(qywxImageExternalBaseDTO);
        }
    }

    private void attachmentAddVideo(List<QywxExternalMessageBaseDTO> attachments, WelcomeMediaBO media, String corpid) {
        String mediaUrl = media.getMediaUrl();
        String[] arr = mediaUrl.split("/");
        JSONResponse jp = qywxSuiteApiService.uploadMedia(corpid, config.getWxSuiteid(),
                CommonUtil.getFileByte(mediaUrl), arr[arr.length - 1], QywxMediaTypeEnum.VIDEO.getCode());
        log.info("欢迎语发送视频返回：{}", JSON.toJSONString(jp));
        if (jp.getErrorCode() == 0) {
            QywxVideoExternalBaseDTO qywxVideoExternalBaseDTO = new QywxVideoExternalBaseDTO();
            qywxVideoExternalBaseDTO.setMediaId(jp.getResult().toString());
            attachments.add(qywxVideoExternalBaseDTO);
        }
    }

    private void attachmentAddFile(List<QywxExternalMessageBaseDTO> attachments, WelcomeMediaBO media, String corpid) {
        String mediaUrl = media.getMediaUrl();
        String[] arr = mediaUrl.split("/");
        JSONResponse jp = qywxSuiteApiService.uploadMedia(corpid, config.getWxSuiteid(),
                CommonUtil.getFileByte(mediaUrl), arr[arr.length - 1], QywxMediaTypeEnum.FILE.getCode());
        log.info("欢迎语发送文件返回：{}", JSON.toJSONString(jp));
        if (jp.getErrorCode() == 0) {
            QywxFileExternalBaseDTO qywxFileExternalBaseDTO = new QywxFileExternalBaseDTO();
            qywxFileExternalBaseDTO.setMediaId(jp.getResult().toString());
            attachments.add(qywxFileExternalBaseDTO);
        }
    }

    private void attachmentAddLink(List<QywxExternalMessageBaseDTO> attachments, WelcomeMediaBO media) {
        String mediaTitle = media.getMediaTitle();
        String mediaUrl = media.getMediaUrl();
        QywxLinkExternalBaseDTO qywxLinkExternalBaseDTO = new QywxLinkExternalBaseDTO();
        qywxLinkExternalBaseDTO.setTitle(mediaTitle);
        qywxLinkExternalBaseDTO.setUrl(mediaUrl);
        attachments.add(qywxLinkExternalBaseDTO);
    }

    private void attachmentAddProgram(List<QywxExternalMessageBaseDTO> attachments, WelcomeMediaBO media,
            String wxEnterpriseId) {
        log.info("发送小程序：wxEnterpriseId:{}", wxEnterpriseId);
        String miniprogramSettingId = media.getMiniprogramSettingId();
        TabMiniprogramSetting miniprogramSetting = miniprogramSettingService.getById(miniprogramSettingId);
        if (Objects.isNull(miniprogramSetting) || miniprogramSetting.getStatusFlag() == 0) {
            log.info("小程序不存在或已被删除, miniprogramSettingId:{}", miniprogramSettingId);
            return;
        }
        QywxMiniprogramExternalBaseDTO messageBaseDTO = new QywxMiniprogramExternalBaseDTO();
        messageBaseDTO.setAppid(miniprogramSetting.getAppId());
        messageBaseDTO.setPicMediaId(miniprogramSetting.getMediaId());
        messageBaseDTO.setTitle(miniprogramSetting.getTitle());
        messageBaseDTO.setPage(media.getMiniProgramPage());
        attachments.add(messageBaseDTO);
    }

    private void attachmentAddParamProgram(List<QywxExternalMessageBaseDTO> attachments, String enterpriseId,
            String wxEnterpriseId, String relationKey) {
        if (StringUtils.isEmpty(enterpriseId) || StringUtils.isEmpty(relationKey)) {
            log.info("带参二维码无法发送");
            return;
        }
        log.info("发送带参小程序：wxEnterpriseId:{}", wxEnterpriseId);
        // 发送小程序
        TabMiniprogramSetting miniprogramSetting = miniprogramSettingService.getMiniprogramSetting(wxEnterpriseId,
                enterpriseId);
        if (null == miniprogramSetting) {
            log.info("需要配置小程序配置：wxEnterpriseId:{},enterpriseId:{}", wxEnterpriseId, enterpriseId);
            return;
        }
        QywxMiniprogramExternalBaseDTO messageBaseDTO = new QywxMiniprogramExternalBaseDTO();
        messageBaseDTO.setAppid(miniprogramSetting.getAppId());
        messageBaseDTO.setPicMediaId(miniprogramSetting.getMediaId());
        messageBaseDTO.setTitle(miniprogramSetting.getTitle());
        messageBaseDTO.setPage(config.getMemberOpenPage() + relationKey);
        attachments.add(messageBaseDTO);
    }

    private void attachmentAddParamQrCode(List<QywxExternalMessageBaseDTO> attachments, String enterpriseId,
            String clerkId, String corpid, String relationKey) {
        if (StringUtils.isEmpty(enterpriseId) || StringUtils.isEmpty(clerkId)) {
            log.info("带参小程序无法发送");
            return;
        }
        // 带参数的公众号二维码
        String sceneStr = "QWHY_" + relationKey + "_" + clerkId;
        // 30天失效
        QRcodeDTO qRcodePic = imageService.getQRcodePic(enterpriseId, sceneStr, 2592000);
        log.info("参数的公众号二维码返回：{}", JSON.toJSONString(qRcodePic));
        if (qRcodePic != null) {
            String downloadUrl = qRcodePic.getPicUploadResDTO().downloadUrl;
            String[] arr = downloadUrl.split("/");
            JSONResponse jp = qywxSuiteApiService.uploadMedia(corpid, config.getWxSuiteid(),
                    CommonUtil.getFileByte(downloadUrl), arr[arr.length - 1], QywxMediaTypeEnum.IMAGE.getCode());
            log.info("欢迎语发送带参数的公众号企微二维码返回：{}", JSON.toJSONString(jp));
            if (jp.getErrorCode() == 0) {
                QywxImageExternalBaseDTO qywxImageExternalBaseDTO = new QywxImageExternalBaseDTO();
                qywxImageExternalBaseDTO.setMediaId(jp.getResult().toString());
                attachments.add(qywxImageExternalBaseDTO);
            }
        }
    }

    private String getExternalUserName(WxEnterpriseQwDTO qwDTO, String externalUserId) {
        log.info("查询好友详情,externalUserId={}", externalUserId);
        String userInfo = qywxUserApiService.getExternalUseridInfo(qwDTO.getThirdCorpid(), config.getWxSuiteid(),
                externalUserId);
        String name = "";
        if (StringUtils.isBlank(userInfo)) {
            log.info("好友不存在");
            return name;
        }
        if ("1".equals(userInfo)) {
            log.info("限制次数");
            return name;
        }
        if (StringUtils.isNotBlank(userInfo)) {
            JSONObject userJson = JSON.parseObject(userInfo);
            String external_contact = userJson.getString("external_contact");
            JSONObject jt = null;
            if (StringUtils.isNotBlank(external_contact)) {
                jt = JSON.parseObject(external_contact);
                name = EmojiFilterUtil.filterEmojiLast(jt.getString("name"), true);
            }
        }
        return name;
    }

    private String getClerkId(String wxEnterpriseId, String staffId, String state) {
        String hyClerkId = null;
        Long hmId = null;
        if (StringUtils.isNotBlank(state)
                && (state.startsWith(Manage3Constants.HM) || state.startsWith(Manage3Constants.DT))) {
            String id = state.substring(2);
            if (state.startsWith(Manage3Constants.HM)) {
                hmId = Convert.toLong(id);
            } else if (state.startsWith(Manage3Constants.DT)) {
                KeyDataLinkBO linkData = keyDataService.getDataForHmLink(id);
                if (null != linkData) {
                    hmId = linkData.getHmId();
                }
            }
            if (null != hmId) {
                HmQrcodeDTO hmDTO = hmQrcodeApiService.getSimpleById(hmId);
                if (hmDTO != null) {
                    hyClerkId = this.getHmClerk(hmDTO, wxEnterpriseId, staffId);
                    log.info("获取到活码导购={},hmId={}", hyClerkId, hmId);
                }
            }
        }
        if (StringUtils.isEmpty(hyClerkId)) {
            TabHaobanClerkMainStoreRelated mainStoreRelated = clerkMainStoreRelatedService
                    .getMainStoreByStaffId(staffId, wxEnterpriseId);
            if (mainStoreRelated != null) {
                StaffClerkRelationDTO staffClerkRelationDTO = staffClerkRelationService.getOneBindByStoreId(staffId,
                        mainStoreRelated.getStoreId());
                if (null != staffClerkRelationDTO) {
                    hyClerkId = staffClerkRelationDTO.getClerkId();
                    log.info("获取成员关联导购={}", hyClerkId);
                }
            }
        }
        return hyClerkId;
    }

    @Override
    public String getHmClerk(HmQrcodeDTO hmDTO, String wxEnterpriseId, String staffId) {
        Long hmId = hmDTO.getHmId();
        if (hmDTO.getHmType() == 1) {
            return hmDTO.getClerkId();
        } else if (hmDTO.getHmType() == 2) {
            // 有主门店导购绑定主导购，没有主门店导购绑定第一个导购，其余随机
            HmClerkRelationDTO hmClerkRelationDTO = null;
            TabHaobanClerkMainStoreRelated mainStoreRelated = clerkMainStoreRelatedService
                    .getMainStoreByStaffId(staffId, wxEnterpriseId);
            if (mainStoreRelated != null) {
                StaffClerkRelationDTO relationDTO = staffClerkRelationService.getOneBindByStoreId(staffId,
                        mainStoreRelated.getStoreId());
                hmClerkRelationDTO = hmClerkRelationApiService.getHmClerkByHmIdAndClerkId(hmId,
                        relationDTO.getClerkId());
                if (hmClerkRelationDTO == null) {
                    hmClerkRelationDTO = hmClerkRelationApiService.getOneHmClerkByHmIdAndStaffId(hmId, staffId);
                    if (hmClerkRelationDTO == null) {
                        hmClerkRelationDTO = hmClerkRelationApiService.getOneHmClerkByHmId(hmId);
                    }
                }
            } else {
                hmClerkRelationDTO = hmClerkRelationApiService.getOneHmClerkByHmId(hmId);
            }
            return hmClerkRelationDTO.getClerkId();
        }
        return null;
    }
}
