package com.ruoyi.system.service.visit.impl;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.system.domain.grid.*;
import com.ruoyi.system.domain.system.SysOtherappAttachment;
import com.ruoyi.system.domain.system.enums.AttachEnums;
import com.ruoyi.system.domain.visit.*;
import com.ruoyi.system.domain.visit.ext.VisitFreeInterviewExt;
import com.ruoyi.system.domain.visit.ext.VisitFreePlanModelExt;
import com.ruoyi.system.mapper.grid.GridHouseMapper;
import com.ruoyi.system.mapper.grid.GridPeopleMapper;
import com.ruoyi.system.mapper.visit.VisitFreeInterviewMapper;
import com.ruoyi.system.mapper.visit.VisitFreePlanModelMapper;
import com.ruoyi.system.service.grid.*;
import com.ruoyi.system.service.system.SysOtherappAttachmentService;
import com.ruoyi.system.service.visit.VisitFreeInterviewService;
import com.ruoyi.system.service.visit.VisitFreePlanService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class VisitAsyncServiceImpl {

    private static final Logger LOGGER = LoggerFactory.getLogger(VisitAsyncServiceImpl.class);

    @Autowired
    VisitFreeInterviewMapper visitFreeInterviewMapper;

    @Autowired
    SysOtherappAttachmentService sysOtherappAttachmentService;

    @Autowired
    VisitFreePlanService visitFreePlanService;

    @Autowired
    VisitFreePlanModelMapper visitFreePlanModelMapper;

    @Autowired
    VisitFreeInterviewService visitFreeInterviewService;

    @Autowired
    GridRegionService gridRegionService;

    @Autowired
    GridCompanyService gridCompanyService;

    @Autowired
    GridShopService gridShopService;

    @Autowired
    GridHouseService gridHouseService;

    @Autowired
    GridHouseMapper gridHouseMapper;

    @Autowired
    GridPeopleService gridPeopleService;

    @Autowired
    GridPeopleMapper gridPeopleMapper;

    @Autowired
    GridRegionUserService gridRegionUserService;


    private static String comma = ",";

    @Transactional(rollbackFor = RuntimeException.class)
    public AjaxResult addVisitFreeInterview(VisitFreeInterviewExt visitFreeInterview) {

        VisitFreePlanExample planExample = new VisitFreePlanExample();
        planExample.createCriteria().andWgCodeEqualTo(visitFreeInterview.getWgyCode())
                .andStartTimeLessThanOrEqualTo(visitFreeInterview.getActualTime())
                .andEndTimeGreaterThanOrEqualTo(visitFreeInterview.getActualTime())
                .andVisitTypeEqualTo(visitFreeInterview.getVisitType())
                .andIsValidEqualTo("1");

        List<VisitFreePlan> freePlanList = visitFreePlanService.selectByExample(planExample);

        freePlanList = freePlanList.stream().filter(o -> !"4".equals(o.getHasDone())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(freePlanList)) {
            if (freePlanList.size() > 1) {
                LOGGER.error("对应网格及走访时间存在多条走访计划");
                return AjaxResult.success(null);
            }

            VisitFreePlan freePlan = freePlanList.get(0);

            //校验是否存在相同走访计划
            VisitFreeInterviewExample interviewCheckExample = new VisitFreeInterviewExample();
            interviewCheckExample.createCriteria().andWgyCodeEqualTo(visitFreeInterview.getWgyCode())
                    .andIsValidEqualTo("1").andPlanIdEqualTo(freePlan.getId()).andVisitTypeEqualTo(visitFreeInterview.getVisitType())
                    .andObjIdEqualTo(visitFreeInterview.getObjId()).andTypeEqualTo(visitFreeInterview.getType());
            Long checkCount = visitFreeInterviewMapper.countByExample(interviewCheckExample);
            if (checkCount > 0) {
                LOGGER.error("对应网格走访任务下已存在相同对象类型记录");
                return AjaxResult.success(null);
            }

            //插入走访日志
            String id = UUID.randomUUID().toString();

            //附件
            if (!CollectionUtils.isEmpty(visitFreeInterview.getOtherappAttachments())) {
                for (SysOtherappAttachment attachment : visitFreeInterview.getOtherappAttachments()) {
                    attachment.setAttachType(AttachEnums.AttachType.FREE_PLAN_INTERVIEW.name());
                    attachment.setBusinessId(id);
                    sysOtherappAttachmentService.insertSelective(attachment);
                }
            }

            visitFreeInterview.setId(id);
            visitFreeInterviewMapper.insertSelective(visitFreeInterview);

            VisitFreeInterviewExample interviewExample = new VisitFreeInterviewExample();
            interviewExample.createCriteria().andWgyCodeEqualTo(visitFreeInterview.getWgyCode())
                    .andIsValidEqualTo("1").andActualTimeGreaterThanOrEqualTo(freePlan.getStartTime()).andVisitTypeEqualTo(visitFreeInterview.getVisitType())
                    .andActualTimeLessThanOrEqualTo(freePlan.getEndTime()).andTypeEqualTo(visitFreeInterview.getType());
            List<VisitFreeInterview> interviews = visitFreeInterviewMapper.selectByExample(interviewExample);

            Map<String, List<VisitFreeInterview>> interviewMap = interviews.stream().collect(Collectors.groupingBy(VisitFreeInterview::getObjId));

            Long num = null == interviewMap ? 0L : interviewMap.size();

            switch (visitFreeInterview.getType()) {
                case "1":
                    freePlan.setComNum(num);
                    break;
                case "2":
                    freePlan.setShopNum(num);
                    break;
                case "3":
                    freePlan.setHouseNum(num);
                    break;
                case "4":
                    freePlan.setPeopleNum(num);
                    break;
            }

            if (freePlan.getComNum() + freePlan.getShopNum() + freePlan.getHouseNum() + freePlan.getPeopleNum() >= freePlan.getPlanTotal()) {
                freePlan.setHasDone("4");
            }

            visitFreePlanService.updateByPrimaryKeySelective(freePlan);

            visitFreeInterview.setPlanId(freePlan.getId());
            visitFreeInterview.setModelId(freePlan.getPlanModelId());
            visitFreeInterviewMapper.updateByPrimaryKeySelective(visitFreeInterview);
        }

        return AjaxResult.success(null);
    }

    @Async
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult dealFreePlan(VisitFreePlanModelExt visitFreePlanModel) {

        VisitFreePlanModel planModel = visitFreePlanModelMapper.selectByPrimaryKey(visitFreePlanModel.getId());
        if (null == planModel) {
            planModel = visitFreePlanModel;
        }

        BeanUtils.copyProperties(visitFreePlanModel, planModel);

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date startTime = sdf.parse(planModel.getStartTime());
                if (startTime.compareTo(new Date()) > 0) {
                    planModel.setPlanStatus("3");
                    visitFreePlanModelMapper.updateByPrimaryKeySelective(planModel);
                    return AjaxResult.success(planModel);
                }
            } catch (ParseException e) {
                planModel.setExceptionDesc(planModel.getId() + "发布任务开始时间格式错误");
                planModel.setPlanStatus("5");
                visitFreePlanModelMapper.updateByPrimaryKeySelective(planModel);
                e.printStackTrace();
                return AjaxResult.error(400, planModel.getId() + "发布任务开始时间格式错误");
            }

            List<GridCompany> wsCompanies = new ArrayList<>();
            List<GridShop> wsShops = new ArrayList<>();

            if ("0".equals(planModel.getUnlimited()) && StringUtils.isEmpty(visitFreePlanModel.getTaskFlag())) {
                GridCompanyExample companyExample = new GridCompanyExample();
                companyExample.createCriteria().andIsValidEqualTo(Byte.valueOf("1"))
                        .andWgCodeIsNotNull();
                wsCompanies = gridCompanyService.selectByExample(companyExample);

                GridShopExample shopExample = new GridShopExample();
                shopExample.createCriteria().andValidEqualTo(Byte.valueOf("1"))
                        .andWgCodeIsNotNull();
                wsShops = gridShopService.selectByExample(shopExample);
            } else if ("1".equals(visitFreePlanModel.getTaskFlag())) {
                wsCompanies = visitFreePlanModel.getWsCompanies();
                wsShops = visitFreePlanModel.getGridShops();
            }

            GridRegionExample wgxxbExample = new GridRegionExample();
            GridRegionExample.Criteria wgxxbCriteria = wgxxbExample.createCriteria();
            wgxxbCriteria.andIsValidEqualTo("1");
            wgxxbCriteria.andLevelEqualTo("3");
            List<GridRegion> gridRegions = gridRegionService.selectByExample(wgxxbExample);

            Map<String, String> wgxxbMap = gridRegions.stream().collect(Collectors.toMap(GridRegion::getWgCode, GridRegion::getWgName));

            List<String> wgcodeList = new ArrayList<>();
            for (String wgCode : planModel.getPlanWgCode().split(comma)) {
                wgcodeList.add(wgCode);
            }

            GridRegionUserExample bsWgxxUserExample = new GridRegionUserExample();
            GridRegionUserExample.Criteria criteria = bsWgxxUserExample.createCriteria();
            criteria.andIsValidEqualTo("1").andWgIdIn(wgcodeList);
            List<GridRegionUser> userList = gridRegionUserService.selectByExample(bsWgxxUserExample);

            Map<String, String> wgUserIdMap = userList.stream().collect(Collectors.toMap(GridRegionUser::getWgId, GridRegionUser::getUserId));
            Map<String, String> wgUserNameMap = userList.stream().collect(Collectors.toMap(GridRegionUser::getWgId, GridRegionUser::getYlzd1));
            for (String wgCode : planModel.getPlanWgCode().split(comma)) {
                if (!wgxxbMap.containsKey(wgCode)) {
                    String wgName = gridRegionService.getWgName(wgCode);
                    planModel.setExceptionDesc(planModel.getId() + " 自由走访计划网格 " + wgName + " 不是三级网格");
                    planModel.setPlanStatus("5");
                    visitFreePlanModelMapper.updateByPrimaryKeySelective(planModel);
                    return AjaxResult.error(400, planModel.getId() + "自由走访计划网格" + wgCode + "不是三级网格");
                }

                if (!wgUserIdMap.containsKey(wgCode)) {
                    String wgName = gridRegionService.getWgName(wgCode);
                    planModel.setExceptionDesc(planModel.getId() + " 自由走访计划网格 " + wgName + " 没有对应网格员");
                    planModel.setPlanStatus("5");
                    visitFreePlanModelMapper.updateByPrimaryKeySelective(planModel);
                    return AjaxResult.error(400, planModel.getId() + "自由走访计划网格" + wgCode + "没有对应网格员");
                }

                VisitFreePlan freePlan = new VisitFreePlan();
                BeanUtils.copyProperties(planModel, freePlan);
                freePlan.setPlanTotal(planModel.getPlanAllNum());
                freePlan.setPlanModelId(visitFreePlanModel.getId());

                //非无限制走访 处理 四类走访数量
                if ("0".equals(planModel.getUnlimited())) {
                    Long comCount = wsCompanies.stream().filter(o -> o.getWgCode().contains(wgCode)).count();
                    if (comCount < visitFreePlanModel.getPlanComNum()) {
                        freePlan.setPlanComNum(comCount);
                    }

                    Long shopCount = wsShops.stream().filter(o -> o.getWgCode().contains(wgCode)).count();
                    if (shopCount < visitFreePlanModel.getPlanShopNum()) {
                        freePlan.setPlanShopNum(shopCount);
                    }

                    GridHouseExample houseExample = new GridHouseExample();
                    houseExample.createCriteria().andIsValidEqualTo(Byte.valueOf("1"))
                            .andWgCodeIsNotNull().andWgCodeLike(wgCode + "%");
                    Long houseCount = gridHouseMapper.countByExample(houseExample);
                    if (houseCount < visitFreePlanModel.getPlanHouseNum()) {
                        freePlan.setPlanHouseNum(houseCount);
                    }

                    GridPeopleExample peopleExample = new GridPeopleExample();
                    peopleExample.createCriteria().andIsValidEqualTo(Byte.valueOf("1"))
                            .andWgCodeIsNotNull().andWgCodeLike(wgCode + "%");
                    Long peopleCount = gridPeopleMapper.countByExample(peopleExample);
                    if (peopleCount < visitFreePlanModel.getPlanPeopleNum()) {
                        freePlan.setPlanPeopleNum(peopleCount);
                    }

                    freePlan.setPlanTotal(freePlan.getPlanComNum() + freePlan.getPlanShopNum()
                            + freePlan.getPlanHouseNum() + freePlan.getPlanPeopleNum());
                }

                freePlan.setPlanModelId(visitFreePlanModel.getId());
                freePlan.setId(UUID.randomUUID().toString());
                freePlan.setWgCode(wgCode);
                freePlan.setPlanUserName(wgUserNameMap.get(wgCode));
                freePlan.setUseid(wgUserIdMap.get(wgCode));
                // 默认为无效状态
                freePlan.setIsValid("0");
                visitFreePlanService.insertSelective(freePlan);
            }
            // 能执行到此处说明上面没有异常，更新网格员计划状态为已生成
            VisitFreePlan freePlanSetAllValid = new VisitFreePlan();
            freePlanSetAllValid.setIsValid("1");

            VisitFreePlanExample freePlanExample = new VisitFreePlanExample();
            VisitFreePlanExample.Criteria freePlanC = freePlanExample.createCriteria();
            freePlanC.andPlanModelIdEqualTo(planModel.getId());
            planModel.setPlanStatus("2");
            visitFreePlanModelMapper.updateByPrimaryKeySelective(planModel);
            visitFreePlanService.updateByExampleSelective(freePlanSetAllValid, freePlanExample);
        } catch (Exception e) {
            String errorMsg = org.apache.commons.lang3.StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 1900);
            planModel.setExceptionDesc("系统报错 请联系管理员 :" + errorMsg);
            planModel.setPlanStatus("5");
            visitFreePlanModelMapper.updateByPrimaryKeySelective(planModel);
            e.printStackTrace();
            return AjaxResult.error(400, planModel.getId() + ":" + errorMsg);
        }

        return AjaxResult.success(null);
    }
}
