package com.sckw.manage.service;

import java.io.IOException;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.CooperateStatusEnum;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.excel.utils.EasyExcelUtil;
import com.sckw.manage.dao.KwmCooperateMapper;
import com.sckw.manage.dao.KwmCooperateTypeMapper;
import com.sckw.manage.model.dto.req.CooperateManageQueryReqDto;
import com.sckw.manage.model.entity.KwmCooperate;
import com.sckw.manage.model.entity.KwmCooperateType;
import com.sckw.manage.model.vo.req.CooperateApplyQueryReqVo;
import com.sckw.manage.model.vo.req.CooperateApproveReqVo;
import com.sckw.manage.model.vo.req.IdsReqVo;
import com.sckw.manage.model.vo.req.InitiateReqVo;
import com.sckw.manage.model.vo.res.CooperateManageQueryResVo;
import com.sckw.manage.model.vo.res.FindListGroupResVo;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author czh
 * @desc 合作申请service
 * @date 2023/7/10
 */
@Slf4j
@Service
public class KwmCooperateApplyService {

    @Autowired
    private KwmCooperateMapper kwmCooperateMapper;

    @Autowired
    private CommonBusinessService commonBusinessService;

    @Autowired
    private KwmCooperateTypeMapper kwmCooperateTypeMapper;

    @DubboReference(version = "2.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;

    /**
     * @param reqVo 分页入参
     * @return HttpResult
     * @desc: 查询合作企业列表
     * @author: czh
     * @date: 2023/7/10
     */
    public PageResult queryByPage(CooperateApplyQueryReqVo reqVo) {
        PageHelper.startPage(reqVo.getPage(), reqVo.getPageSize());
        List<CooperateManageQueryResVo> list = commonBusinessService.findList(buildQueryParam(reqVo));
        return PageHelperUtil.getPageResult(new PageInfo<>(list));
    }

    /**
     * @param reqVo 查询入参
     * @return CooperateManageQueryReqDto
     * @desc: 构建查全量入参
     * @author: czh
     * @date: 2023/7/11
     */
    private CooperateManageQueryReqDto buildQueryParam(CooperateApplyQueryReqVo reqVo) {
        CooperateManageQueryReqDto cooperateManageQueryReqDto = new CooperateManageQueryReqDto();
        BeanUtils.copyProperties(reqVo, cooperateManageQueryReqDto);
        String cooperateTypes = reqVo.getCooperateTypes();
        if (!StringUtils.isBlank(cooperateTypes)) {
            cooperateManageQueryReqDto.setCooperateTypes(Arrays.asList(cooperateTypes.split(Global.COMMA)));
        }

        List<Long> ids = reqVo.getIds();
        if (!CollectionUtils.isEmpty(ids)) {
            cooperateManageQueryReqDto.setIds(ids);
        }
        //只允许查出申请中、已拒绝、已撤销的记录
        List<Integer> status = new ArrayList<>();
        if (Objects.isNull(reqVo.getStatus())) {
            status.add(CooperateStatusEnum.PROCESS.getCode());
            status.add(CooperateStatusEnum.REFUSE.getCode());
            status.add(CooperateStatusEnum.CANCEL.getCode());
        }

        if (Objects.nonNull(reqVo.getStatus()) && reqVo.getStatus().equals(CooperateStatusEnum.PROCESS.getCode())) {
            status.add(CooperateStatusEnum.PROCESS.getCode());
        }
        if (Objects.nonNull(reqVo.getStatus()) && reqVo.getStatus().equals(CooperateStatusEnum.REFUSE.getCode())) {
            status.add(CooperateStatusEnum.REFUSE.getCode());
        }
        if (Objects.nonNull(reqVo.getStatus()) && reqVo.getStatus().equals(CooperateStatusEnum.CANCEL.getCode())) {
            status.add(CooperateStatusEnum.CANCEL.getCode());
        }
        cooperateManageQueryReqDto.setStatus(status);
        return cooperateManageQueryReqDto;
    }


    /**
     * @param reqVo 申请入参
     * @desc: 发起申请
     * @author: czh
     * @date: 2023/7/11
     */
    @Transactional(rollbackFor = {})
    public void initiate(InitiateReqVo reqVo) {
        Long currentEntId = LoginUserHolder.getEntId();
        List<Integer> chooseCooperateTypes = Arrays.stream(reqVo.getChooseCooperateTypes().split(Global.COMMA)).map(Integer::parseInt).toList();

        //查是否有在合作中、审核中的记录
        List<KwmCooperate> kwmCooperates = queryValidCooperate(reqVo.getEntId(), currentEntId);
        if (!CollectionUtils.isEmpty(kwmCooperates)) {
            //有待审核的记录不允许新增申请
            if (kwmCooperates.stream().anyMatch(item -> item.getStatus() == CooperateStatusEnum.PROCESS.getCode())) {
                throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.MSG_015);
            }

            //已合作的可以新增，但不能重复新增
            checkTypeRepeat(currentEntId, chooseCooperateTypes, kwmCooperates);
        }

        //保存发起申请
        saveInitiate(reqVo, currentEntId, chooseCooperateTypes);
    }


    /**
     * @param reqVo 入参， currentEntId当前企业id，选择的企业类型
     * @desc: 保存发起申请
     * @author: czh
     * @date: 2023/7/11
     */
    public void saveInitiate(InitiateReqVo reqVo, Long currentEntId, List<Integer> chooseCooperateTypes) {
        Date date = new Date();
        KwmCooperate kwmCooperate = new KwmCooperate();
        long id = new IdWorker(1L).nextId();
        kwmCooperate.setEntId(currentEntId);
        kwmCooperate.setInviterEntId(currentEntId);
        kwmCooperate.setInviteeEntId(reqVo.getEntId());

        //我方联系人
        UserCacheResDto contactDto = remoteSystemService.queryUserCacheById(reqVo.getUserId());
        if (Objects.nonNull(contactDto)) {
            kwmCooperate.setInviterContactsId(contactDto.getId());
            kwmCooperate.setInviterContacts(contactDto.getName());
            kwmCooperate.setInviterPhone(contactDto.getPhone());
        }

        //对方联系人
        UserCacheResDto userCacheResDto = remoteSystemService.queryManagerInfoByEntId(reqVo.getEntId());
        if (Objects.nonNull(userCacheResDto)) {
            kwmCooperate.setInviteeContactsId(userCacheResDto.getId());
            kwmCooperate.setInviteeContacts(contactDto.getName());
            kwmCooperate.setInviteePhone(contactDto.getPhone());
        }

        kwmCooperate.setId(id);
        kwmCooperate.setRemark(reqVo.getRemark());
        kwmCooperate.setStatus(CooperateStatusEnum.PROCESS.getCode());
        kwmCooperate.setCreateBy(LoginUserHolder.getUserId());
        kwmCooperate.setCreateTime(date);
        kwmCooperate.setUpdateBy(LoginUserHolder.getUserId());
        kwmCooperate.setUpdateTime(date);
        kwmCooperate.setDelFlag(Global.NO);
        if (kwmCooperateMapper.insert(kwmCooperate) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }


        chooseCooperateTypes.forEach(item -> {
            KwmCooperateType kwmCooperateType = new KwmCooperateType();
            kwmCooperateType.setId(new IdWorker(1L).nextId());
            kwmCooperateType.setCooperateId(id);
            kwmCooperateType.setType(item);
            kwmCooperateType.setStatus(Global.NO);
            kwmCooperateType.setCreateBy(LoginUserHolder.getUserId());
            kwmCooperateType.setCreateTime(date);
            kwmCooperateType.setUpdateBy(LoginUserHolder.getUserId());
            kwmCooperateType.setUpdateTime(date);
            kwmCooperateType.setDelFlag(Global.NO);
            if (kwmCooperateTypeMapper.insert(kwmCooperateType) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
            }
        });
    }

    /**
     * @param currentEntId 当前企业id  chooseCooperateTypes选择的合作属性  kwmCooperates已有的合作记录
     * @desc: 新增申请前判重
     * @author: czh
     * @date: 2023/7/11
     */
    private void checkTypeRepeat(Long currentEntId, List<Integer> chooseCooperateTypes, List<KwmCooperate> kwmCooperates) {
        for (KwmCooperate kwmCooperate : kwmCooperates) {
            //受邀请方
            Long inviteeEntId = kwmCooperate.getInviteeEntId();
            //发起方
            Long inviterEntId = kwmCooperate.getInviterEntId();
            LambdaQueryWrapper<KwmCooperateType> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(KwmCooperateType::getCooperateId, kwmCooperate.getId());
            List<KwmCooperateType> kwmCooperateTypes = kwmCooperateTypeMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(kwmCooperateTypes)) {
                throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.COOPERATE_ATTRIBUTE_NOT_EXISTS);
            }

            //判断是否有重复的合作属性
            List<Integer> typeList = kwmCooperateTypes.stream().map(KwmCooperateType::getType).toList();
            if (inviterEntId.equals(currentEntId)) {
                chooseCooperateTypes.forEach(item -> {
                    if (typeList.contains(item)) {
                        throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_016);
                    }
                });
            }

            if (inviteeEntId.equals(currentEntId)) {
                chooseCooperateTypes.forEach(item -> {
                    Integer relative = commonBusinessService.changeAttribute(item);
                    if (typeList.contains(relative)) {
                        throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_016);
                    }
                });
            }
        }
    }

    /**
     * @param entId 对方企业id  currentEntId 我方企业id
     * @return KwmCooperate
     * @desc: 查是否有在合作中、审核中的记录
     * @author: czh
     * @date: 2023/7/11
     */
    private List<KwmCooperate> queryValidCooperate(Long entId, Long currentEntId) {
        LambdaQueryWrapper<KwmCooperate> wrapper = new LambdaQueryWrapper<>();
        List<Integer> statusList = new ArrayList<>();
        statusList.add(CooperateStatusEnum.OK.getCode());
        statusList.add(CooperateStatusEnum.PROCESS.getCode());
        wrapper.eq(KwmCooperate::getDelFlag, Global.NO).
                in(KwmCooperate::getStatus, statusList).
                and(wq -> wq.eq(KwmCooperate::getInviteeEntId, entId).
                        eq(KwmCooperate::getInviterEntId, currentEntId).
                        or().
                        eq(KwmCooperate::getInviteeEntId, currentEntId).
                        eq(KwmCooperate::getInviterEntId, entId));
        return kwmCooperateMapper.selectList(wrapper);
    }





    /**
     * @param reqVo 主键
     * @desc: 撤销
     * @author: czh
     * @date: 2023/7/11
     */
    public void cancel(IdsReqVo reqVo) {
        updateCooperateInfo(reqVo.getIds(), CooperateStatusEnum.CANCEL.getCode(), reqVo.getRemark());
    }


    /**
     * @param ids 主键 type需要修改为的类型
     * @desc: 抽取公共方法
     * @author: czh
     * @date: 2023/7/11
     */
    @Transactional(rollbackFor = {})
    public void updateCooperateInfo(String ids, Integer type, String remark) {
        List<Long> idList = Arrays.stream(ids.split(Global.COMMA)).map(Long::parseLong).toList();
        LambdaQueryWrapper<KwmCooperate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwmCooperate::getDelFlag, Global.NO);
        wrapper.in(KwmCooperate::getId, idList);
        List<KwmCooperate> kwmCooperates = kwmCooperateMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(kwmCooperates) || kwmCooperates.size() != idList.size()) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.COOPERATE_NOT_EXISTS);
        }

        Long userId = LoginUserHolder.getUserId();
        Date date = new Date();
        kwmCooperates.forEach(item -> {
            if (item.getStatus() != CooperateStatusEnum.PROCESS.getCode()) {
                throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_019);
            }
            item.setStatus(type);
            item.setUpdateBy(userId);
            item.setUpdateTime(date);
            item.setApprovalRemark(remark);
            if (kwmCooperateMapper.updateById(item) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }


        });
    }


    /**
     * @param reqVo 入参
     * @desc: 审核
     * @author: czh
     * @date: 2023/7/11
     */
    @Transactional(rollbackFor = {})
    public void approve(CooperateApproveReqVo reqVo) {
        updateCooperateInfo(reqVo.getIds(), reqVo.getApprove(), reqVo.getRemark());

        if (reqVo.getApprove().equals(CooperateStatusEnum.OK.getCode())) {
            for (String id : reqVo.getIds().split(Global.COMMA)) {
                commonBusinessService.bingManager(reqVo.getManager(), Long.parseLong(id));
            }
        }
    }


    /**
     * @param reqVo 全量入参
     * @desc: 导出
     * @author: czh
     * @date: 2023/7/11
     */
    public void export(CooperateApplyQueryReqVo reqVo) {
        List<CooperateManageQueryResVo> list = commonBusinessService.findList(buildQueryParam(reqVo));
        try {
            EasyExcelUtil.writeSingleExcel("合作申请.xlsx", "sheet1", list, CooperateManageQueryResVo.class);
        } catch (IOException e) {
            log.error("导出失败:", e);
            throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_014);
        }
    }


    /**
     * @param reqVo 查询入参
     * @return HttpResult
     * @desc: 分组查询
     * @author: czh
     * @date: 2023/7/17
     */
    public List<FindListGroupResVo> findListGroup(CooperateApplyQueryReqVo reqVo) {
        //初始化分组返参
        List<FindListGroupResVo> result = commonBusinessService.init();

        List<CooperateManageQueryResVo> list = commonBusinessService.findList(buildQueryParam(reqVo));
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }

        //填充分组数据
        commonBusinessService.fillGroup(result, list);
        return result;
    }




}
