package com.gic.haoban.manage.web.controller.chat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.BasePageInfo;
import com.gic.api.base.commons.JSONResponse;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.AuthorizedUser;
import com.gic.commons.util.PageHelperUtils;
import com.gic.commons.util.ToolUtil;
import com.gic.commons.web.RequestThreadLocal;
import com.gic.commons.webapi.reponse.RestResponse;
import com.gic.enterprise.api.dto.EnterpriseDTO;
import com.gic.enterprise.api.dto.security.DownloadReportDTO;
import com.gic.enterprise.api.service.DownloadReportService;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.haoban.base.api.common.pojo.dto.WebLoginDTO;
import com.gic.haoban.common.utils.AuthWebRequestUtil;
import com.gic.haoban.manage.api.dto.chat.GroupChatDTO;
import com.gic.haoban.manage.api.dto.chat.GroupChatHmDTO;
import com.gic.haoban.manage.api.dto.hm.HmLinkChatDTO;
import com.gic.haoban.manage.api.dto.qdto.chat.ChatHmSearchQDTO;
import com.gic.haoban.manage.api.dto.qdto.chat.GroupChatSearchQDTO;
import com.gic.haoban.manage.api.dto.qdto.hm.HmLinkChatQDTO;
import com.gic.haoban.manage.api.service.chat.GroupChatApiService;
import com.gic.haoban.manage.api.service.chat.GroupChatHmApiService;
import com.gic.haoban.manage.web.log.LogRecordUserServiceImpl;
import com.gic.haoban.manage.web.utils.CreatorUtils;
import com.gic.haoban.manage.web.vo.chat.GroupChatHmVO;
import com.gic.haoban.manage.web.vo.chat.HmLinkChatListVO;
import com.gic.log.record.anno.GicLogRecord;
import com.gic.log.record.util.GicLogRecordCategoryEnum;
import com.gic.log.record.util.GicLogRecordEvaluationContext;
import com.gic.log.record.util.GicLogRecordOptTypeEnum;
import com.gic.thirdparty.cloudfile.CloudFileUtil;
import com.gic.thirdparty.cloudfile.enums.CloudFileBusinessOptEnum;
import com.gic.thirdparty.cloudfile.enums.CloudFileTypeEnum;
import com.gic.thirdparty.cloudfile.pojo.CloudFileInfo;
import com.gic.web.common.utils.DataPermissionExport;
import com.gic.web.common.utils.ExecutorPoolSingleton;
import com.google.common.collect.Sets;

/**
 * 
* @ClassName: GroupChatHmController
* @Description: 群活码
* @author xugh
* @date 2022年11月26日 上午9:32:56
*
 */
@RestController
@RequestMapping("/chat/hm")
public class GroupChatHmController {

    private static Logger logger = LogManager.getLogger(GroupChatHmController.class);

    @Autowired
    private GroupChatHmApiService groupChatHmApiService;
    @Autowired
    private GroupChatApiService groupChatApiService;
    @Autowired
    private DownloadReportService downloadReportService;
    @Autowired
    private EnterpriseService enterpriseService;

    @RequestMapping("add")
    @GicLogRecord(value = "${#logValue}", category = GicLogRecordCategoryEnum.HB_QHM, optType = GicLogRecordOptTypeEnum.HB_1002_01, userFunc = LogRecordUserServiceImpl.class, optPage = "群活码-新建活码")
    public RestResponse<Object> save(@RequestBody GroupChatHmDTO dto) {
        if (CollectionUtils.isEmpty(dto.getChatIdList())) {
            GicLogRecordEvaluationContext.noWriteLog();
            return RestResponse.failure("1", "请选择加入的群");
        }
        if (dto.getChatIdList().size() > 4) {
            GicLogRecordEvaluationContext.noWriteLog();
            return RestResponse.failure("1", "最多可选4个群");
        }
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        dto.setCreatorId(loginUser.getClerkId());
        dto.setCreatorName(loginUser.getClerkName());
        dto.setModifierId(loginUser.getClerkId());
        dto.setModifierName(loginUser.getClerkName());
        dto.setWxEnterpriseId(loginUser.getWxEnterpriseId());
        dto.setEnterpriseId(loginUser.getEnterpriseId());
        ServiceResponse<GroupChatHmDTO> resp = this.groupChatHmApiService.save(dto);
        if (resp.isSuccess()) {
            String logContent = "新增群活码【" + resp.getResult().getChatHmCode() + "-" + dto.getName() + "】";
            GicLogRecordEvaluationContext.putAttribute("logValue", logContent);
            GicLogRecordEvaluationContext.putOptTargetId(AuthWebRequestUtil.getLoginUser().getClerkId());
            return RestResponse.successResult();
        }
        GicLogRecordEvaluationContext.noWriteLog();
        return RestResponse.failure("1", resp.getMessage());
    }

    @RequestMapping("update")
    @GicLogRecord(value = "${#logValue}", category = GicLogRecordCategoryEnum.HB_QHM, optType = GicLogRecordOptTypeEnum.HB_1002_02, userFunc = LogRecordUserServiceImpl.class, optPage = "群活码-编辑活码")
    public RestResponse<Object> update(@RequestBody GroupChatHmDTO dto) {
        if (CollectionUtils.isEmpty(dto.getChatIdList())) {
            GicLogRecordEvaluationContext.noWriteLog();
            return RestResponse.failure("1", "请选择加入的群");
        }
        if (dto.getChatIdList().size() > 4) {
            GicLogRecordEvaluationContext.noWriteLog();
            return RestResponse.failure("1", "最多可选4个群");
        }
        if (null == dto.getChatHmId()) {
            GicLogRecordEvaluationContext.noWriteLog();
            return RestResponse.failure("1", "ID为空");
        }
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        ServiceResponse<GroupChatHmDTO> oldResp = this.groupChatHmApiService.detail(dto.getChatHmId());
        if (!oldResp.isSuccess()) {
            return RestResponse.failure(oldResp.getCode(), oldResp.getMessage());
        }
        List<Long> oldIdList = this.groupChatHmApiService
                .listHmGroupChatId(loginUser.getWxEnterpriseId(), dto.getChatHmId()).getResult();
        GroupChatHmDTO oldDTO = oldResp.getResult();
        dto.setWxEnterpriseId(loginUser.getWxEnterpriseId());
        dto.setEnterpriseId(loginUser.getEnterpriseId());
        dto.setModifierId(loginUser.getClerkId());
        dto.setModifierName(loginUser.getClerkName());
        dto.setWxConfigId(oldDTO.getWxConfigId());
        ServiceResponse<GroupChatHmDTO> resp = this.groupChatHmApiService.save(dto);
        if (resp.isSuccess()) {
            String logContent = this.getUpdateLog(oldDTO, dto, oldIdList);
            if (StringUtils.isNotBlank(logContent)) {
                GicLogRecordEvaluationContext.putAttribute("logValue", logContent);
                GicLogRecordEvaluationContext.putOptTargetId(AuthWebRequestUtil.getLoginUser().getClerkId());
            } else {
                GicLogRecordEvaluationContext.noWriteLog();
            }
            return RestResponse.successResult();
        }
        GicLogRecordEvaluationContext.noWriteLog();
        return RestResponse.failure("1", resp.getMessage());
    }

    private String getUpdateLog(GroupChatHmDTO oldDTO, GroupChatHmDTO newDTO, List<Long> oldIdList) {
        String wxEnterpriseId = newDTO.getWxEnterpriseId();
        String enterpriseId = newDTO.getEnterpriseId();
        StringBuilder content = new StringBuilder();
        String a = comp(wxEnterpriseId, enterpriseId, "群活码名称", oldDTO.getName(), newDTO.getName(), 0);
        if (null != a) {
            content.append(a);
        }
        String b = comp(wxEnterpriseId, enterpriseId, "群活码描述", oldDTO.getRemark(), newDTO.getRemark(), 0);
        if (null != b) {
            content.append(b);
        }

        String o = null;
        List<Long> newIdList = newDTO.getChatIdList();

        Sets.SetView<Long> delView = Sets.difference(Sets.newHashSet(oldIdList), Sets.newHashSet(newIdList));
        List<Long> delIdList = delView.stream().collect(Collectors.toList());
        logger.info("删除的群={}", delIdList);
        if (CollectionUtils.isNotEmpty(delIdList)) {
            String chats = this.getGroupChatName(wxEnterpriseId, delIdList);
            if (StringUtils.isNotBlank(chats)) {
                o = "删除可加入群聊【" + chats + "】";
                content.append(o);
            }
        }
        String p = null;
        Sets.SetView<Long> addView = Sets.difference(Sets.newHashSet(newIdList), Sets.newHashSet(oldIdList));
        List<Long> addIdList = addView.stream().collect(Collectors.toList());
        logger.info("增加的群={}", addIdList);
        if (CollectionUtils.isNotEmpty(addIdList)) {
            String chats = this.getGroupChatName(wxEnterpriseId, addIdList);
            if (StringUtils.isNotBlank(chats)) {
                p = "新增可加入群聊【" + chats + "】";
                content.append(p);
            }
        }

        String c = null;
        if (oldDTO.getAutoCreateRoom() == 1 && newDTO.getAutoCreateRoom() == 0) {
            c = "关闭自动建群功能";
            content.append(c);
        }
        String d = null;
        if (oldDTO.getAutoCreateRoom() == 0 && newDTO.getAutoCreateRoom() == 1) {
            d = "开启自动建群功能【" + newDTO.getRoomBaseName() + newDTO.getRoomBaseId() + "】";
            content.append(d);
        }
        String e = null;
        String f = null;
        if (null == c && d == null) {
            e = comp(wxEnterpriseId, enterpriseId, "群名前缀", oldDTO.getRoomBaseName(), newDTO.getRoomBaseName(), 0);
            if (null != e) {
                content.append(e);
            }
            f = comp(wxEnterpriseId, enterpriseId, "群起始序号", oldDTO.getRoomBaseId() + "", newDTO.getRoomBaseId() + "",
                    0);
            if (null != f) {
                content.append(f);
            }
        }
        if (org.apache.commons.lang3.StringUtils.isAllBlank(a, b, c, d, e, f, o, p)) {
            return null;
        }
        StringBuilder sb = new StringBuilder("编辑群活码").append("【").append(oldDTO.getChatHmCode()).append("-")
                .append(oldDTO.getName()).append("】：");
        return sb.append(content).toString();
    }

    private String getGroupChatName(String wxEnterpriseId, List<Long> groupChatIdList) {
        ServiceResponse<List<GroupChatDTO>> resp = this.groupChatApiService.listChatByIdList(wxEnterpriseId,
                groupChatIdList);
        List<GroupChatDTO> list = resp.getResult();
        String names = list.stream().map(dto -> joint(dto.getWxChatId(), "-", dto.getName()))
                .collect(Collectors.joining(","));
        return names;
    }

    private String joint(String... arr) {
        StringBuilder sb = new StringBuilder();
        for (String s : arr) {
            sb.append(s);
        }
        return sb.toString();
    }

    public String comp(String wxEnterpriseId, String enterpriseId, String title, String oldValue, String newValue,
            int type) {
        StringBuilder sb = new StringBuilder();
        if (null == oldValue) {
            oldValue = "";
        }
        if (null == newValue) {
            newValue = "";
        }
        if (type == 0 && !oldValue.equals(newValue)) {
            sb.append(title).append("「").append(oldValue).append("」变更为「").append(newValue).append("」");
            return sb.toString();
        }
        return null;
    }

    @RequestMapping("page")
    public RestResponse<Object> page(@RequestBody ChatHmSearchQDTO qdto) {
        BasePageInfo basePageInfo = new BasePageInfo();
        basePageInfo.setPageNum(qdto.getPageNum());
        basePageInfo.setPageSize(qdto.getPageSize());
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        qdto.setWxEnterpriseId(loginUser.getWxEnterpriseId());
        qdto.setEnterpriseId(loginUser.getEnterpriseId());
        List<String> creatorIdList = CreatorUtils.getCreatorIdList(0);
        if (CollectionUtils.isNotEmpty(creatorIdList)) {
            qdto.setCreatorIdList(creatorIdList);
        }
        ServiceResponse<Page<GroupChatHmDTO>> pageResp = this.groupChatHmApiService.listPage(qdto, basePageInfo);
        Page<GroupChatHmDTO> page = pageResp.getResult();
        Page<GroupChatHmVO> retPage = PageHelperUtils.changePageToCurrentPage(page, GroupChatHmVO.class);
        if (CollectionUtils.isNotEmpty(retPage.getResult())) {
            retPage.getResult().forEach(vo -> {
                if (vo.getUsableChatCount() == 0) {
                    vo.setUseRemark("无可加入的群聊");
                }
            });
        }
        return RestResponse.successResult(retPage);
    }

    @RequestMapping("detail")
    public RestResponse<Object> detail(Long chatHmId) {
        if (null == chatHmId) {
            return RestResponse.failure("1", "群活码ID空");
        }
        ServiceResponse<GroupChatHmDTO> linkResp = this.groupChatHmApiService.detail(chatHmId);
        if (!linkResp.isSuccess()) {
            return RestResponse.failure("1", "群活码不存在");
        }
        GroupChatHmDTO hm = linkResp.getResult();
        return RestResponse.successResult(hm);
    }

    /**
     * 
    * @Title: discard
    * @Description: 废弃活码
    * @author xugh
    * @param chatHmId
    * @return
    * @throws
     */
    @RequestMapping("discard")
    @GicLogRecord(value = "${#logValue}", category = GicLogRecordCategoryEnum.HB_QHM, optType = GicLogRecordOptTypeEnum.HB_1002_03, userFunc = LogRecordUserServiceImpl.class, optPage = "群活码")
    public RestResponse<Object> discard(Long chatHmId, @RequestParam(defaultValue = "0") int page) {
        if (null == chatHmId) {
            GicLogRecordEvaluationContext.noWriteLog();
            return RestResponse.failure("1", "群活码ID空");
        }
        // 判断是否关联链接
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        String wxEnterpriseId = loginUser.getWxEnterpriseId();
        String clerkId = loginUser.getClerkId();
        String clerkName = loginUser.getClerkName();
        ServiceResponse<GroupChatHmDTO> respDTO = this.groupChatHmApiService.detail(chatHmId);
        ServiceResponse<Void> resp = this.groupChatHmApiService.discard(chatHmId, wxEnterpriseId, clerkId, clerkName);
        if (resp.isSuccess()) {
            String logContent = "废弃群活码【" + respDTO.getResult().getChatHmCode() + "-" + respDTO.getResult().getName()
                    + "】";
            GicLogRecordEvaluationContext.putAttribute("logValue", logContent);
            if (page == 1) {
                GicLogRecordEvaluationContext.setOptPage("群活码-详情");
            }
            GicLogRecordEvaluationContext.putOptTargetId(AuthWebRequestUtil.getLoginUser().getClerkId());
            return RestResponse.successResult();
        }
        GicLogRecordEvaluationContext.noWriteLog();
        return RestResponse.failure("1", resp.getMessage());
    }

    /**
     * 
    * @Title: linkRelation
    * @Description: 查询使用此活码的链接列表
    * @author xugh
    * @param chatHmId
    * @param basePageInfo
    * @return
    * @throws
     */
    @RequestMapping("link-relation")
    public RestResponse<Object> linkRelation(Long chatHmId, BasePageInfo basePageInfo) {
        if (null == chatHmId) {
            return RestResponse.failure("1", "群活码ID空");
        }
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        String wxEnterpriseId = loginUser.getWxEnterpriseId();
        HmLinkChatQDTO qdto = new HmLinkChatQDTO();
        qdto.setWxEnterpriseId(wxEnterpriseId);
        qdto.setEnterpriseId(loginUser.getEnterpriseId());
        qdto.setChatHmId(chatHmId);
        ServiceResponse<Page<HmLinkChatDTO>> pageResp = this.groupChatHmApiService.listPageChatLink(qdto, basePageInfo);
        Page<HmLinkChatDTO> page = pageResp.getResult();
        Page<HmLinkChatListVO> retPage = PageHelperUtils.changePageToCurrentPage(page, HmLinkChatListVO.class);
        return RestResponse.successResult(retPage);
    }

    /**
     * 
    * @Title: groupRelation
    * @Description: 查询群活码关联的群列表
    * @author xugh
    * @param chatHmId
    * @param basePageInfo
    * @return
    * @throws
     */
    @RequestMapping("group-relation")
    public RestResponse<Object> groupRelation(Long chatHmId, BasePageInfo basePageInfo,
            @RequestParam(defaultValue = "0") int includeOff) {
        if (null == chatHmId) {
            return RestResponse.failure("1", "群活码ID空");
        }
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        String wxEnterpriseId = loginUser.getWxEnterpriseId();
        GroupChatSearchQDTO qdto = new GroupChatSearchQDTO();
        qdto.setWxEnterpriseId(wxEnterpriseId);
        qdto.setEnterpriseId(loginUser.getEnterpriseId());
        qdto.setChatHmId(chatHmId);
        qdto.setIncludeOff(includeOff);
        ServiceResponse<Page<GroupChatDTO>> pageResp = this.groupChatApiService.listPage(qdto, basePageInfo);
        Page<GroupChatDTO> page = pageResp.getResult();
        List<GroupChatDTO> list = page.getResult();
        if (CollectionUtils.isNotEmpty(list)) {
            list.stream().forEach(dto -> {
                if (dto.getTotalCount() >= 200) {
                    dto.setHmAddStatus(2);
                }
            });
        }
        return RestResponse.successResult(page);
    }

    @SuppressWarnings("deprecation")
    @RequestMapping("download")
    public RestResponse<Object> download(@RequestBody ChatHmSearchQDTO qdto) {
        int allFlag = qdto.getAllFlag();
        if (allFlag == 0 && CollectionUtils.isEmpty(qdto.getChatHmIdList())) {
            return RestResponse.failure("1", "请选择要下载的群活码");
        }
        if (allFlag == 1) {
            qdto.setChatHmIdList(null);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String qrCodeName = "群活码";
        final String fileName = qrCodeName + "_" + sdf.format(new Date()) + ".zip";
        WebLoginDTO loginUser = AuthWebRequestUtil.getLoginUser();
        String wxEnterpriseId = loginUser.getWxEnterpriseId();
        String enterpriseId = loginUser.getEnterpriseId();
        final AuthorizedUser au = new AuthorizedUser();
        au.setEnterpriseId(enterpriseId);
        au.setUserId(loginUser.getClerkId());
        au.setRealName(loginUser.getClerkName());
        EnterpriseDTO enterpriseDTO = this.enterpriseService.getEnterpriseById(enterpriseId);
        final String factoryCode = enterpriseDTO.getFactoryCode();
        String path = RequestThreadLocal.get().getSession().getServletContext().getRealPath("/chat/qrcode/");
        String uuId = ToolUtil.randomUUID();
        path = path + uuId;
        final String tempPath = path + File.separator + fileName;

        File file = new File(tempPath);
        if (!file.exists()) {
            file.getParentFile().mkdirs();
            try {
                file.createNewFile();
            } catch (IOException e) {
            }
        }
        qdto.setEnterpriseId(enterpriseId);
        qdto.setWxEnterpriseId(wxEnterpriseId);
        qdto.setStatus(1);
        BasePageInfo basePageInfo = new BasePageInfo();
        basePageInfo.setPageNum(1);
        basePageInfo.setPageSize(500000);
        ServiceResponse<Page<GroupChatHmDTO>> resp = this.groupChatHmApiService.listPage(qdto, basePageInfo);
        List<GroupChatHmDTO> dtoList = resp.getResult().getResult();

        int size = dtoList.size();
        JSONResponse jsonResponse = DataPermissionExport.generatedExcel(1, au, "", "", size, fileName, qrCodeName,
                downloadReportService);
        final String reportId;
        if (jsonResponse.isSuccess()) {
            reportId = (String) jsonResponse.getResult();
        } else {
            return RestResponse.failure("1", jsonResponse.getMessage());
        }
        ExecutorPoolSingleton.getInstance().executeTask(new Runnable() {
            @Override
            public void run() {
                try {
                    File tempFile = new File(tempPath);
                    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tempFile));
                    for (GroupChatHmDTO dto : dtoList) {
                        String qrCodeUrl = dto.getWxQrCode();
                        logger.info("下载={}", qrCodeUrl);
                        if (StringUtils.isNotBlank(qrCodeUrl)) {
                            try {
                                ZipEntry e = new ZipEntry(dto.getChatHmCode() + "_" + dto.getName() + ".png");
                                out.putNextEntry(e);
                                out.write(getStoreQrCode(qrCodeUrl));
                                out.flush();
                            } catch (IOException e) {
                            }
                        }
                    }
                    try {
                        out.flush();
                        out.closeEntry();
                        out.close();
                    } catch (IOException e) {
                    }
                    CloudFileTypeEnum cloudFileTypeEnum = CloudFileTypeEnum.OTHER;
                    logger.info("下载={}", factoryCode);
                    CloudFileInfo cloudFileInfo = CloudFileUtil.uploadFile(new FileInputStream(tempFile), "zip",
                            cloudFileTypeEnum, factoryCode, CloudFileBusinessOptEnum.HAOBAN_COMMON);
                    logger.info("下载={}", JSON.toJSONString(cloudFileInfo));
                    DownloadReportDTO downloadReportDTO = new DownloadReportDTO();
                    downloadReportDTO.setDownloadUrl(cloudFileInfo.getOrgFileUrl());
                    downloadReportService.updateDownloadReport(reportId, downloadReportDTO);
                    tempFile.deleteOnExit();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        return RestResponse.successResult(reportId);
    }

    private byte[] getStoreQrCode(String qrCodeUrl) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(qrCodeUrl);
            try {
                conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                InputStream in = conn.getInputStream();
                return IOUtils.toByteArray(in);
            } catch (IOException e) {
                return null;
            }
        } catch (MalformedURLException e) {
            return null;
        }
    }

}
