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

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.commons.util.EntityUtil;
import com.gic.enterprise.api.dto.EnterpriseDTO;
import com.gic.enterprise.api.dto.StoreDTO;
import com.gic.enterprise.api.dto.StoreDetailDTO;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.enterprise.api.service.StoreService;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.common.utils.UuidUtil;
import com.gic.haoban.manage.api.dto.*;
import com.gic.haoban.manage.api.enums.*;
import com.gic.haoban.manage.api.service.*;
import com.gic.haoban.manage.api.util.notify.NoticeMessageUtil;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanAuditMapper;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanBatchAuditLogMapper;
import com.gic.haoban.manage.service.entity.TabHaobanAudit;
import com.gic.haoban.manage.service.entity.TabHaobanBatchAuditLog;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.github.pagehelper.PageHelper;
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 org.springframework.transaction.annotation.Transactional;

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

/**
 * Created by tgs on 2020/2/9.
 */
@Service
public class AuditApiServiceImpl implements AuditApiService {

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

    @Autowired
    private TabHaobanAuditMapper auditMapper;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private StoreService storeService;
    @Autowired
    private TabHaobanBatchAuditLogMapper tabHaobanBatchAuditLogMapper;
    @Autowired
    private StaffDepartmentRelatedApiService staffDepartmentRelatedApiService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private SyncHaobanToGicApiService syncHaobanToGicApiService;
    @Autowired
    private StaffClerkRelationApiService staffClerkRelationApiService;
    @Autowired
    private ClerkService clerkService;
    @Autowired
    private StaffApiService staffApiService;

    @Override
    public Page<AuditDTO> page(Integer auditType, String search, String wxEnterpriseId,
                               String enterpriseId, Integer auditStatus, Integer auditFlag, BasePageInfo pageInfo, String clerkId) {
        List<String> storeIdList = staffApiService.getHaoBanStoreIdsRolesByClerkId(clerkId, wxEnterpriseId);
        if (CollectionUtils.isEmpty(storeIdList)) {
            return PageUtil.emptyPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        }
        if (storeIdList.contains("-1")) {
            storeIdList = null;
        }
        PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        com.github.pagehelper.Page<TabHaobanAudit> page = auditMapper.page(wxEnterpriseId, auditType, storeIdList, search, enterpriseId, auditStatus, auditFlag);
        if (CollectionUtil.isNotEmpty(page.getResult())) {
            List<String> commitStaffIds = page.getResult().stream().filter(item -> StringUtils.isBlank(item.getCommitStaffName())).map(s -> s.getCommitStaffId()).collect(Collectors.toList());
            logger.info(JSON.toJSONString(commitStaffIds));
            if (CollectionUtil.isNotEmpty(commitStaffIds)) {
                List<TabHaobanStaff> staffList = staffMapper.listByIds(commitStaffIds);
                Map<String, TabHaobanStaff> map = com.gic.commons.util.CollectionUtil.toMap(staffList, "staffId");
                for (TabHaobanAudit tab : page.getResult()) {
                    String commitStaffId = tab.getCommitStaffId();
                    tab.setCommitStaffName(map.get(commitStaffId) == null ? "" : map.get(commitStaffId).getStaffName());
                    tab.setCommitStaffImg(map.get(commitStaffId) == null ? "" : map.get(commitStaffId).getHeadImg());
                }
            }
        }
        return PageUtil.changePageHelperToCurrentPage(page, AuditDTO.class);
    }

    @Transactional
    @Override
    public String audit(String batchId, String auditId, String auditName, String optStaffId) {
        TabHaobanAudit tab = auditMapper.selectByPrimaryKey(auditId);
        if (tab == null) {
            return "审核项目不存在";
        }
        int auditType = tab.getAuditType();
        tab.setAuditId(auditId);
        tab.setUpdateTime(new Date());
        tab.setAuditName(auditName);
        tab.setAuditStaffId(optStaffId);
        if (auditType == AuditType.STORE_CHANGE.getCode()) {
            //门店信息变更
            String storeId = tab.getCommitStoreId();
            String oldValue = tab.getOldValue();
            String newValue = tab.getNewValue();
            String changeField = tab.getChangeField();
            StoreDTO store = storeService.getStore(storeId);
            if (store == null) {
                return "门店不存在";
            }
            this.editStoreInfo(storeId, changeField, oldValue, newValue);
            //发送消息
            String content = StoreFieldEnum.getValueName(changeField);
            content = "[" + content + "]" + "修改审核通过";
            TabHaobanAudit tab2 = auditMapper.selectByPrimaryKey(auditId);
            String staffId = tab2.getCommitStaffId();
            //插入log
            if (StringUtils.isNotBlank(batchId)) {
                insertBatchLog(batchId, AuditRsultType.success.getCode(), tab);
            }
            this.sendMessageByStaffId(staffId, storeId, false, content, "");
        } else if (auditType == AuditType.CLERK_BIND.getCode()) {
            //门店导购绑定
            String oldValue = tab.getOldValue();
            AuditStaffDTO obj = JSONObject.parseObject(oldValue, AuditStaffDTO.class);
            StaffClerkRelationDTO staffClerkRelation = staffClerkRelationApiService.getByCodeAndEnterpriseId(obj.getClerkCode(), tab.getEnterpriseId());
            String staffId = obj.getStaffId();
            String storeId = tab.getCommitStoreId();
            String clerkId = obj.getClerkId();
            StaffClerkRelationDTO have = staffClerkRelationApiService.getOneByStoreIdAndStaffId(storeId, staffId);
            ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
            if (have != null) {
                tab.setAuditStatus(5);
                String reason = "该成员在该门店下已经绑定过一个导购了";
                if (clerkDTO != null) {
                    Integer clerkType = clerkDTO.getClerkType();
                    if (clerkType == 2) {
                        reason = "该成员在该商户下已经绑定过一个区经了";
                    }
                }
                tab.setAuditReason(reason);
                auditMapper.updateByPrimaryKeySelective(tab);
                if (StringUtils.isNotBlank(batchId)) {
                    insertBatchLog(batchId, AuditRsultType.fail.getCode(), tab);
                }
                staffDepartmentRelatedApiService.sendBindAuditMessage(auditId, obj.getStaffId(), clerkId, reason, true);
                return reason;
            }
            if (clerkDTO == null) {
                tab.setAuditStatus(5);
                String reason = "gic已删除该导购";
                tab.setAuditReason(reason);
                auditMapper.updateByPrimaryKeySelective(tab);
                if (StringUtils.isNotBlank(batchId)) {
                    insertBatchLog(batchId, AuditRsultType.fail.getCode(), tab);
                }
                staffDepartmentRelatedApiService.sendBindAuditMessage(auditId, obj.getStaffId(), clerkId, tab.getAuditReason(), true);
                return reason;
            } else {
                if (staffClerkRelation == null) {
                    staffClerkRelation = new StaffClerkRelationDTO();
                }
                staffClerkRelation.setEnterpriseId(tab.getEnterpriseId());
                staffClerkRelation.setClerkCode(obj.getClerkCode());
                staffClerkRelation.setClerkId(clerkId);
                staffClerkRelation.setStoreId(tab.getCommitStoreId());
                staffClerkRelation.setWxEnterpriseId(tab.getWxEnterpriseId());
                staffClerkRelation.setStaffId(obj.getStaffId());
                staffClerkRelation.setManageFlag(clerkDTO.getClerkType() == 2 ? 1 : 0);
                ServiceResponse serviceResponse = staffClerkRelationApiService.wxBindStaffClerk(staffClerkRelation, optStaffId, ChannelCodeEnum.AUDIT_BIND.getCode());
                if (!serviceResponse.isSuccess()) {
                    return serviceResponse.getMessage();
                }
            }
            if (StringUtils.isNotBlank(batchId)) {
                insertBatchLog(batchId, AuditRsultType.success.getCode(), tab);
            }
            //同意绑定
            staffDepartmentRelatedApiService.sendBindAuditMessage(auditId, obj.getStaffId(), clerkId, "", false);
        } else if (auditType == AuditType.CLERK_ADD.getCode()) {
            //门店导购新增
            String oldValue = tab.getOldValue();
            AuditStaffDTO obj = JSONObject.parseObject(oldValue, AuditStaffDTO.class);
            String flag = syncHaobanToGicApiService.syncClerkToGicClerkAddNew(tab.getCommitStoreId(), obj.getClerkCode(), obj.getSex(), obj.getClerkName(), obj.getPhoneNumber(), obj.getNationCode(), null);
            if (!"1".equals(flag)) {
                //失败
                tab.setAuditStatus(5);
                tab.setAuditReason(flag);
                auditMapper.updateByPrimaryKeySelective(tab);
                if (StringUtils.isNotBlank(batchId)) {
                    insertBatchLog(batchId, AuditRsultType.fail.getCode(), tab);
                }
                return flag;
            } else {
                //成功
                if (StringUtils.isNotBlank(batchId)) {
                    insertBatchLog(batchId, 1, tab);
                }
                staffDepartmentRelatedApiService.sendClerkAdd(obj.getClerkName(), obj.getClerkCode(), tab.getCommitStoreId(), 1, "");
            }

        } else if (auditType == AuditType.CLERK_DEL.getCode()) {
            //门店导购删除
            String oldValue = tab.getOldValue();
            AuditStaffDTO obj = JSONObject.parseObject(oldValue, AuditStaffDTO.class);
            syncHaobanToGicApiService.delGicClerk(obj.getClerkId());
            if (StringUtils.isNotBlank(batchId)) {
                insertBatchLog(batchId, AuditRsultType.success.getCode(), tab);
            }
            staffClerkRelationApiService.unbindByStaffAndClerkId(optStaffId, obj.getClerkId(), ChannelCodeEnum.AUDIT_UNBIND.getCode(),obj.getWxEnterpriseId());
            staffDepartmentRelatedApiService.sendClerkDel(obj.getClerkName(), obj.getClerkCode(), tab.getCommitStoreId(), 1, "");
        } else if (auditType == AuditType.CLERK_UNBIND.getCode()) {
            //解绑申请，无需审核，直接通过
            logger.info("解绑申请，无需审核，直接通过");
        }
        tab.setAuditStatus(1);
        auditMapper.updateByPrimaryKeySelective(tab);
        return "";
    }

    @Override
    public void refuse(String auditId, String auditReason, String auditStaffId, String auditName) {
        TabHaobanAudit tab = new TabHaobanAudit();
        tab.setAuditId(auditId);
        tab.setAuditStatus(2);
        tab.setUpdateTime(new Date());
        tab.setAuditReason(auditReason);
        tab.setAuditName(auditName);
        tab.setAuditStaffId(auditStaffId);
        auditMapper.updateByPrimaryKeySelective(tab);
        TabHaobanAudit tab2 = auditMapper.selectByPrimaryKey(auditId);
        int auditType = tab2.getAuditType();
        String oldValue = tab2.getOldValue();
        //发送消息
        if (auditType == AuditType.STORE_CHANGE.getCode()) {
            String changeField = tab2.getChangeField();
            String content = StoreFieldEnum.getValueName(changeField);
            String staffId = tab2.getCommitStaffId();
            String storeId = tab2.getCommitStoreId();
            this.sendMessageByStaffId(staffId, storeId, true, content, auditReason);
        } else if (auditType == AuditType.CLERK_BIND.getCode()) {
            AuditStaffDTO obj = JSONObject.parseObject(oldValue, AuditStaffDTO.class);
            String staffId = tab2.getCommitStaffId();
            staffDepartmentRelatedApiService.sendBindAuditMessage(auditId, staffId, obj.getClerkId(), auditReason, true);
        } else if (auditType == AuditType.CLERK_ADD.getCode()) {
            AuditStaffDTO obj = JSONObject.parseObject(oldValue, AuditStaffDTO.class);
            staffDepartmentRelatedApiService.sendClerkAdd(obj.getClerkName(), obj.getClerkCode(), tab2.getCommitStoreId(), 2, auditReason);
        } else if (auditType == AuditType.CLERK_DEL.getCode()) {
            AuditStaffDTO obj = JSONObject.parseObject(oldValue, AuditStaffDTO.class);
            staffDepartmentRelatedApiService.sendClerkDel(obj.getClerkName(), obj.getClerkCode(), tab2.getCommitStoreId(), 2, auditReason);
        }
    }

    @Override
    public int save(Integer auditType, String wxEnterpriseId, String enterpriseId,
                    String commitStaffId, String commitStoreId, String changeField,
                    String oldValue, String newValue) {
        TabHaobanStaff staff = staffMapper.selectByPrimaryKey(commitStaffId);
        if (staff == null) {
            return 0;
        }
        TabHaobanAudit tab = new TabHaobanAudit();
        tab.setAuditId(UuidUtil.randomUUID());
        tab.setAuditStatus(0);
        tab.setAuditType(auditType);
        tab.setChangeField(changeField);
        tab.setCommitName(null);
        tab.setCommitStaffId(commitStaffId);
        tab.setCommitStaffImg(staff.getHeadImg());
        tab.setCommitStaffName(staff.getStaffName());
        tab.setCommitStoreId(commitStoreId);
        StoreDTO store = this.storeService.getStore(commitStoreId);
        if (null != store) {
            tab.setCommitStoreName(store.getStoreName());
        }
        tab.setCommitTime(new Date());
        tab.setCreateTime(new Date());
        tab.setWxEnterpriseId(wxEnterpriseId);
        tab.setEnterpriseId(enterpriseId);
        tab.setNewValue(newValue);
        tab.setOldValue(oldValue);
        tab.setStatusFlag(1);
        tab.setUpdateTime(new Date());
        return auditMapper.insert(tab);
    }

    @Override
    public void editStoreInfo(String storeId, String changeField,
                              String oldValue, String newValue) {
        logger.info("===================进11");
        StoreDTO store = storeService.getStore(storeId);
        if (!StoreFieldEnum.STORE_IMAG.getValue().equals(changeField)) {
            //非门店图片修改
            logger.info("===================进222");
            StoreDetailDTO detailDTO = new StoreDetailDTO();
            detailDTO = EntityUtil.changeEntityByJSON(StoreDetailDTO.class, store);
            detailDTO.setStoreId(storeId);
            detailDTO.setEnterpriseId(store.getEnterpriseId());
            //detailDTO.setStatus(2);
            detailDTO.setOpenTime(null);
            detailDTO.setCloseTime(null);
            getStoreDTO(detailDTO, changeField, oldValue, newValue);

            logger.info("detailDTO====================>为{}", JSONObject.toJSONString(detailDTO));
            storeService.saveStore(detailDTO);
        } else {
            //门店图片修改
            logger.info("===================进333");
            storeService.updateStorePhotos(storeId, newValue);
        }
    }

    private void getStoreDTO(StoreDetailDTO store, String changeField, String oldValue, String newValue) {
        logger.info("==========================>changeField={}", changeField);
        if (StoreFieldEnum.BUSINESS_TIME_STRING.getValue().equals(changeField)) {
            //营业时间
            String[] newValues = newValue.split("-");
            String openTime = newValues[0];
            String closeTime = newValues[1];
            store.setOpenTime(openTime);
            store.setCloseTime(closeTime);
        } else if (StoreFieldEnum.CONACTS_PHONE.getValue().equals(changeField)) {
            //联系电话
            store.setConactsPhone(newValue);
        } else if (StoreFieldEnum.STORE_ADDRESS.getValue().equals(changeField)) {
            logger.info("==========================>进来333");
            //门店地址
            StoreAddressDTO obj = JSONObject.parseObject(newValue, StoreAddressDTO.class);
            String areaId = obj.getAreaId();
            String storeAddress = obj.getStoreAddress();
            logger.info("==========================>areaId={},storeAddress={},newValue={}", areaId, storeAddress, newValue);
            String[] arr = storeAddress.split(" ");
            store.setAreaId(areaId);
            store.setFullArea(arr[0]);
            //避免多个空格造成数据混乱
            store.setStoreAddress(storeAddress.substring(storeAddress.indexOf(arr[0]) + arr[0].length() + 1));
        } else if (StoreFieldEnum.STORE_AREA.getValue().equals(changeField)) {
            //门店面积
            store.setStoreArea(Double.parseDouble(newValue));
        } else if (StoreFieldEnum.STORE_NAME.getValue().equals(changeField)) {
            //门店名字
            store.setStoreName(newValue);
        } else if (StoreFieldEnum.STORE_IMAG.getValue().equals(changeField)) {
            //门店图片
        }
    }

    @Override
    public List<AuditDTO> listByStoreId(String storeId) {
        List<TabHaobanAudit> list = auditMapper.listByStoreId(storeId);
        List<AuditDTO> resultList = EntityUtil.changeEntityListByJSON(AuditDTO.class, list);
        return resultList;
    }

    @Override
    public AuditDTO findByStoreIdAndChangeField(String storeId,
                                                String changeField) {
        TabHaobanAudit tab = auditMapper.findByStoreIdAndChangeField(storeId, changeField);
        if (tab == null) {
            return null;
        }
        return EntityUtil.changeEntityByJSON(AuditDTO.class, tab);
    }


    private void sendMessageByStaffId(String staffId, String storeId, boolean isRefuse, String content, String reason) {
        StaffClerkRelationDTO staffClerkRelationDTO = staffClerkRelationApiService.getOneByStoreIdAndStaffId(storeId, staffId);
        if (staffClerkRelationDTO == null) {
            logger.info("staff不存在");
            return;
        }

        Map<String, String> params = new HashMap<String, String>();
        params.put("field", content);
        params.put("reason", reason);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("storeId", storeId);

        if (isRefuse) {
            NoticeMessageUtil.sendNoticeMessage(staffClerkRelationDTO.getEnterpriseId(), staffClerkRelationDTO.getClerkId()
                    , NoticeMessageTypeEnum.STORE_EDIT_REFUSE.getType(), null, params, jsonObject);

        } else {
            NoticeMessageUtil.sendNoticeMessage(staffClerkRelationDTO.getEnterpriseId(), staffClerkRelationDTO.getClerkId()
                    , NoticeMessageTypeEnum.STORE_EDIT_AGREE.getType(), null, params, jsonObject);
        }
    }

    @Override
    public void insert(AuditDTO audit) {
        audit.setAuditId(com.gic.haoban.common.utils.StringUtil.randomUUID());
        audit.setCreateTime(new Date());
        audit.setUpdateTime(new Date());
        auditMapper.insert(EntityUtil.changeEntityByJSON(TabHaobanAudit.class, audit));
    }

    @Override
    public Page<AuditDTO> listByStaffId(String staffId, Integer auditType, Integer auditStatus, String enterpriseId, BasePageInfo pageInfo) {
        PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        return PageUtil.changePageHelperToCurrentPage(auditMapper.listByStaffId(staffId, auditType, auditStatus, enterpriseId), AuditDTO.class);
    }

    @Override
    public Page<AuditDTO> pageStoreListByParams(List<String> storeIds, BasePageInfo pageInfo, Integer auditType,
                                                Integer auditStatus, String wxEnterpriseId, String enterpriseId) {
        PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
        return PageUtil.changePageHelperToCurrentPage(auditMapper.pageStoreListByParams(storeIds, auditType, auditStatus, wxEnterpriseId, enterpriseId), AuditDTO.class);
    }

    public void insertBatchLog(String batchId, int auditResult, TabHaobanAudit tab) {
        EnterpriseDTO enterprise = enterpriseService.getEnterpriseById(tab.getEnterpriseId());
        TabHaobanBatchAuditLog batTab = new TabHaobanBatchAuditLog();
        batTab.setAuditId(tab.getAuditId());
        batTab.setBatchAuditLogId(UuidUtil.randomUUID());
        batTab.setAuditType(tab.getAuditType());
        batTab.setAuditResult(auditResult);
        batTab.setBatchId(batchId);
        batTab.setCommitName(tab.getCommitStaffName());
        batTab.setCommitTime(tab.getCommitTime());
        batTab.setCreateTime(new Date());
        batTab.setEnterpriseName(enterprise == null ? "" : enterprise.getEnterpriseName());
        batTab.setStatus(1);
        batTab.setUpdateTime(new Date());
        tabHaobanBatchAuditLogMapper.insert(batTab);
    }

    @Override
    public AuditDTO findById(String auditId) {
        return EntityUtil.changeEntityByJSON(AuditDTO.class, auditMapper.selectByPrimaryKey(auditId));
    }

    @Override
    public void update(AuditDTO audit) {
        audit.setUpdateTime(new Date());
        auditMapper.updateByPrimaryKeySelective(EntityUtil.changeEntityByJSON(TabHaobanAudit.class, audit));
    }

    @Override
    public List<BatchAuditLogDTO> listBatchLog(String batchId) {
        List<TabHaobanBatchAuditLog> list = tabHaobanBatchAuditLogMapper.listByBatchId(batchId);
        return EntityUtil.changeEntityListByJSON(BatchAuditLogDTO.class, list);
    }

    @Override
    public AuditDTO findByBindRelatedIdAndAuditType(String relatedId, int auditType, String wxEnterpriseId, String enterpriseId) {
        TabHaobanAudit tab = auditMapper.findByBindRelatedIdAndAuditType(relatedId, auditType, wxEnterpriseId, enterpriseId);
        return EntityUtil.changeEntityByJSON(AuditDTO.class, tab);
    }

    @Override
    public boolean judgeHavePhoneNumberOrCode(String enterpriseId,
                                              String clerkCode, String phoneNumber, String wxEnterpriseId) {
        List<TabHaobanAudit> list = auditMapper.judgeHavePhoneNumberOrCode(enterpriseId, clerkCode, phoneNumber, wxEnterpriseId);
        return !CollectionUtil.isEmpty(list);
    }

    @Override
    public int getAuditCount(String wxEnterpriseId, String enterpriseId, String clerkId) {
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(clerkId);
        if (clerkDTO == null) {
            return 0;
        }
        List<String> storeIdList = new ArrayList<>();
        Integer clerkType = clerkDTO.getClerkType();
        String storeId = clerkDTO.getStoreId();
        if (clerkType == 2) {
            // 如果null,说明是所有门店
            storeIdList = staffApiService.getHaoBanStoreIdsRolesByClerkId(clerkId, wxEnterpriseId);
            if (CollectionUtils.isEmpty(storeIdList)) {
                return 0;
            }
            if (storeIdList.contains("-1")) {
                storeIdList = null;
            }
            clerkId = null;
        } else {
            storeIdList.add(storeId);
            //店长查询门店
            if (clerkType == 1) {
                clerkId = null;
            }
        }
        return this.auditMapper.getAuditCount(wxEnterpriseId, enterpriseId, clerkId, storeIdList);
    }

}
