package cn.com.ty.lift.business.project.service;

import cn.com.ty.lift.business.capital.dao.entity.model.request.CapitalRepairRequest;
import cn.com.ty.lift.business.capital.dao.mapper.CapitalRepairLiftRelevanceMapper;
import cn.com.ty.lift.business.framework.util.MessageUtils;
import cn.com.ty.lift.business.library.dao.entity.Lift;
import cn.com.ty.lift.business.library.dao.entity.PlatformCompanyLiftRelevance;
import cn.com.ty.lift.business.library.dao.entity.model.request.LiftExtensionRequest;
import cn.com.ty.lift.business.library.service.LiftService;
import cn.com.ty.lift.business.library.service.PlatformCompanyLiftRelevanceService;
import cn.com.ty.lift.business.maintenance.dao.entity.model.CapitalCount;
import cn.com.ty.lift.business.maintenance.dao.entity.model.MaintenanceCount;
import cn.com.ty.lift.business.maintenance.dao.entity.model.request.MaintenanceRecordRequest;
import cn.com.ty.lift.business.maintenance.dao.entity.model.response.MaintenanceAppResponse;
import cn.com.ty.lift.business.maintenance.dao.mapper.MaintenancePlanMapper;
import cn.com.ty.lift.business.maintenance.dao.mapper.MaintenanceRecordMapper;
import cn.com.ty.lift.business.maintenance.service.MaintenanceService;
import cn.com.ty.lift.business.project.dao.entity.Project;
import cn.com.ty.lift.business.project.dao.entity.ProjectLiftRelevance;
import cn.com.ty.lift.business.project.dao.entity.model.ProjectAppUser;
import cn.com.ty.lift.business.project.dao.entity.model.request.ProjectRequest;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectCompanyResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectDetailResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectLiftResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectUserResponse;
import cn.com.ty.lift.business.project.dao.mapper.ProjectMapper;
import cn.com.ty.lift.business.project.dao.mapper.ProjectUserMapper;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static cn.com.ty.lift.common.constants.CommonEnum.*;

/**
 * @author bieao
 * @date 2019/12/31
 * @description app端项目管理业务层
 */
@Slf4j
@Service
public class ProjectAppService extends ServiceImpl<ProjectMapper, Project> {

    @Resource
    private LiftService liftService;

    @Resource
    private ProjectService projectService;

    @Resource
    private ProjectUserMapper projectUserMapper;

    @Resource
    private ProjectUserService projectUserService;

    @Resource
    private MaintenancePlanMapper maintenancePlanMapper;

    @Resource
    private MaintenanceRecordMapper maintenanceRecordMapper;

    @Resource
    private CapitalRepairLiftRelevanceMapper capitalRepairLiftRelevanceMapper;

    @Resource
    private ProjectLiftRelevanceService projectLiftRelevanceService;

    @Resource
    private MaintenanceService maintenanceService;

    @Resource
    private PlatformCompanyLiftRelevanceService platformService;

    /**
     * @param request 公司id
     * @return RestResponse 项目列表
     * @description 根据公司id查询公司下项目列表
     * @date 2019/12/31 4:25 PM
     */
    public IPage<ProjectCompanyResponse> companyList(ProjectRequest request) {
        return baseMapper.findListByCompanyId(request.getPage(), request);
    }

    /**
     * @param request 项目id、公司id
     * @return List<ProjectUser> 项目下维保工
     * @description 获取项目下维保工
     * @date 2020/1/14 10:33 上午
     */
    public List<ProjectAppUser> userList(ProjectRequest request) {
        List<ProjectAppUser> userList = projectUserMapper.findProjectUserListById(request);
        String currentRoleCode = request.getCurrentRoleCode();
        Long userId = request.getUserId();
        List<ProjectAppUser> workerList = new ArrayList<>();
        if (DefaultRole.MTWORK.getCode().equals(currentRoleCode)) {
            userList.forEach(entry -> {
                if (Objects.equals(userId, entry.getUserId())) {
                    workerList.add(entry);
                }
            });
            return workerList;
        } else {
            return userList.stream().filter(
                    entry -> (DefaultRole.MTWORK.getCode().equals(entry.getUserRole())
                            || DefaultRole.REGION_DIRECTOR.getCode().equals(entry.getUserRole())))
                    .collect(Collectors.toList());
        }
    }

    /**
     * @param request 项目id
     * @return RestResponse 电梯列表
     * @description 根据项目id查询项目下电梯列表
     * @date 2019/12/31 3:13 PM
     */
    public IPage<ProjectLiftResponse> projectLiftList(ProjectRequest request) {
        if (DefaultRole.MTWORK.getCode().equals(request.getCurrentRoleCode())) {
            String globalSet = maintenanceRecordMapper.getGlobalSet(request.getMtCompanyId());
            if (Objects.isNull(globalSet)) globalSet = "0";
            //是否能查看到项目下其他维保工的电梯
            request.setLook(Objects.equals("0", globalSet) ? "0" : "1");
        }
        return baseMapper.findListByProjectId(request.getPage(), request);
    }

    /**
     * @param mtCompanyId      公司id
     * @param registrationCode 注册代码
     * @return RestResponse 判断结果
     * @description 新增电梯前置判断条件
     * @date 2019/12/20 2:31 PM
     */
    public boolean preJudgment(Long mtCompanyId, String registrationCode) {
        //查询电梯表是否有该电梯
        Optional<Lift> lift = liftService.getOne(registrationCode, null);
        Long liftId = lift.map(Lift::getId).orElse(null);
        if (ObjectUtil.isNotEmpty(liftId)) {
            Map<String, Object> paramMap = new HashMap<>(2);
            paramMap.put("liftId", liftId);
            paramMap.put("mtCompanyId", mtCompanyId);
            //查询该公司下是否有此电梯
            boolean result = platformService.findCompanyLiftExist(paramMap);
            return !result;
        } else return true;
    }

    /**
     * @param request 新增电梯数据项
     * @return RestResponse 状态码和返回消息
     * @description 新增电梯
     * @date 2020/1/11 4:22 下午
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse add(LiftExtensionRequest request) {
        Long mtCompanyId = request.getMtCompanyId();
        Lift lift = request.getLift();
        if (!preJudgment(mtCompanyId, lift.getRegistrationCode()))
            return RestResponse.fail(MessageUtils.get("msg.lift.exist"));

        //检查电梯是否需要新增
        Optional<Lift> lifts = liftService.getOne(lift.getRegistrationCode(), null);
        Long checkLiftId = lifts.map(Lift::getId).orElse(null);
        if (!ObjectUtil.isNotEmpty(checkLiftId)) {
            boolean result = liftService.save(lift);
            if (!result) {
                return RestResponse.fail(MessageUtils.get("msg.add.fail"));
            }
        }
        Long liftId = lift.getId();
        //判断当前公司台量是否大于企业设置的台量
        if (!maintenanceService.judge(mtCompanyId))
            return RestResponse.fail(MessageUtils.get("msg.limit.num"));

        PlatformCompanyLiftRelevance companyLiftEntry = liftService.saveCompanyLiftInfo(liftId, mtCompanyId);
        if (Objects.isNull(companyLiftEntry)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.add.fail"));
        }
        Long projectId = request.getProjectId();
        Optional<Project> optional = projectService.getOne(projectId);
        int num = 0;
        if (optional.isPresent()) {
            Project project = optional.get();
            num = project.getNum();
        }
        //判断当前项目下实际台量是否大于项目里设置的台量
        int currentNum = projectLiftRelevanceService.countLiftNum(mtCompanyId, projectId);
        if (currentNum >= num) {
            return RestResponse.fail(MessageUtils.get("msg.project.limit.num"));
        }
        //新增项目电梯关联表
        ProjectLiftRelevance projectLiftRelevance = projectLiftRelevanceService
                .save(lift.getId(), request.getProjectId(), companyLiftEntry.getId(), request.getWorkerId(), mtCompanyId);
        if (Objects.isNull(projectLiftRelevance)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.add.fail"));
        }
        //新增电梯发送消息
        liftService.sendAddMessage(liftId, projectLiftRelevance.getProjectId(), mtCompanyId);
        return RestResponse.success(null, MessageUtils.get("msg.add.success"));
    }

    /**
     * @param projectId 项目id
     * @return RestResponse 项目详情
     * @description 根据项目id查询项目详情
     * @date 2020/1/2 1:50 下午
     */
    public ProjectDetailResponse detail(Long projectId) {
        return baseMapper.findProjectById(projectId);
    }

    /**
     * @param request 用户ID，公司ID
     * @return Map<String, Long> 统计分组结果
     * @description 保养任务日历统计
     * @date 2020/4/30 2:15 下午
     */
    public List<MaintenanceCount> count(MaintenanceRecordRequest request) {
        request.setEndTime(request.getBeginTime().with(TemporalAdjusters.lastDayOfMonth()));
        if (DefaultRole.MTWORK.getCode().equals(request.getCurrentRoleCode())) {
            String globalSet = maintenanceRecordMapper.getGlobalSet(request.getMtCompanyId());
            if (Objects.isNull(globalSet)) globalSet = "0";
            //维保工不能查看到项目组其他维保工的任务
            request.setLook(Objects.equals("0", globalSet) ? "0" : "1");
        }
        //总经理查询所有保养任务
        if (DefaultRole.HIGH_DIRECTOR.getCode().equals(request.getCurrentRoleCode())) {
            request.setUserId(null);
        }
        List<MaintenanceCount> planCountResult = maintenancePlanMapper.countPlanByWorkerId(request);
        Set<LocalDate> set = planCountResult.stream().map(MaintenanceCount::getPlanDate).collect(Collectors.toSet());

        List<MaintenanceCount> recordCountResult = maintenanceRecordMapper.countRecordByWorkerId(request);
        List<LocalDate> recordDateList = recordCountResult.stream().map(MaintenanceCount::getPlanDate).collect(Collectors.toList());
        set.addAll(recordDateList);

        List<MaintenanceCount> resultList = new ArrayList<>();
        for (LocalDate entry : set) {
            MaintenanceCount count = new MaintenanceCount();
            count.setPlanDate(entry);
            Optional<MaintenanceCount> plan = planCountResult.stream().filter(maintenanceCount -> maintenanceCount.getPlanDate().equals(entry)).findFirst();
            plan.ifPresent(p -> {
                count.setWaitingMaintenance(p.getWaitingMaintenance());
                count.setOverdue(p.getOverdue());
            });

            Optional<MaintenanceCount> record = recordCountResult.stream().filter(maintenanceCount -> maintenanceCount.getPlanDate().equals(entry)).findFirst();
            record.ifPresent(r -> {
                count.setInProgress(r.getInProgress());
                count.setComplete(r.getComplete());
            });
            resultList.add(count);
        }
        return resultList;
    }

    /**
     * @param request 用户id和维保状态
     * @return RestResponse 保养任务列表 （待完成、超期）
     * @description 根据用户id和维保状态查询保养任务列表
     * @date 2020/1/6 11:29 上午
     */
    public IPage<MaintenanceAppResponse> planTask(MaintenanceRecordRequest request) {
        if (Objects.nonNull(request.getBeginTime())) {
            request.setEndTime(request.getBeginTime().with(TemporalAdjusters.lastDayOfMonth()));
        }
        if (DefaultRole.MTWORK.getCode().equals(request.getCurrentRoleCode())) {
            String globalSet = maintenanceRecordMapper.getGlobalSet(request.getMtCompanyId());
            if (Objects.isNull(globalSet)) globalSet = "0";
            //维保工不能查看到项目组其他维保工的任务
            request.setLook(Objects.equals("0", globalSet) ? "0" : "1");
        }
        //总经理查询所有保养任务
        if (DefaultRole.HIGH_DIRECTOR.getCode().equals(request.getCurrentRoleCode())) {
            request.setUserId(null);
        }
        IPage<MaintenanceAppResponse> page = maintenancePlanMapper.findPlanByWorkerId(request.getPage(), request);
        List<MaintenanceAppResponse> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {

            Map<Long, List<MaintenanceAppResponse>> currentTaskMap = page.getRecords().stream().filter(entry ->
                    Objects.equals(request.getUserId(), entry.getWorkerId())).collect(Collectors.groupingBy(MaintenanceAppResponse::getLiftId));
            List<MaintenanceAppResponse> taskList = new ArrayList<>();
            for (Map.Entry<Long, List<MaintenanceAppResponse>> entry : currentTaskMap.entrySet()) {
                taskList.addAll(entry.getValue());
            }

            LinkedList<MaintenanceAppResponse> currentUserTaskList = taskList.stream()
                    .sorted(Comparator.comparing(MaintenanceAppResponse::getPlanDate)).collect(Collectors.toCollection(LinkedList::new));

            Map<Long, List<MaintenanceAppResponse>> taskMap = page.getRecords().stream().filter(entry ->
                    !Objects.equals(request.getUserId(), entry.getWorkerId())).collect(Collectors.groupingBy(MaintenanceAppResponse::getLiftId));

            taskList.clear();
            for (Map.Entry<Long, List<MaintenanceAppResponse>> entry : taskMap.entrySet()) {
                taskList.addAll(entry.getValue());
            }
            LinkedList<MaintenanceAppResponse> userTaskList = taskList.stream()
                    .sorted(Comparator.comparing(MaintenanceAppResponse::getPlanDate)).collect(Collectors.toCollection(LinkedList::new));
            currentUserTaskList.addAll(userTaskList);

            page.setRecords(currentUserTaskList);
        }
        return page;
    }

    /**
     * @param request 用户id和维保状态
     * @return RestResponse 保养任务列表
     * @description 根据用户id和维保状态查询保养任务列表
     * @date 2020/4/24 5:03 下午
     */
    public IPage<MaintenanceAppResponse> recordTask(MaintenanceRecordRequest request) {
        if (Objects.nonNull(request.getBeginTime())) {
            request.setEndTime(request.getBeginTime().with(TemporalAdjusters.lastDayOfMonth()));
        }
        log.info("角色名称：" + request.getCurrentRoleCode());
        if (DefaultRole.MTWORK.getCode().equals(request.getCurrentRoleCode())) {
            String globalSet = maintenanceRecordMapper.getGlobalSet(request.getMtCompanyId());
            if (Objects.isNull(globalSet)) globalSet = "0";
            //维保工不能查看到项目组其他维保工的任务
            request.setLook(Objects.equals("0", globalSet) ? "0" : "1");
        }
        //总经理查询所有保养任务
        if (DefaultRole.HIGH_DIRECTOR.getCode().equals(request.getCurrentRoleCode())) {
            request.setUserId(null);
        }
        IPage<MaintenanceAppResponse> page = maintenanceRecordMapper.findRecordByWorkerId(request.getPage(), request);
        List<MaintenanceAppResponse> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            Map<Long, List<MaintenanceAppResponse>> currentTaskMap = page.getRecords().stream().filter(entry ->
                    Objects.equals(request.getUserId(), entry.getWorkerId1())).collect(Collectors.groupingBy(MaintenanceAppResponse::getLiftId));
            List<MaintenanceAppResponse> taskList = new ArrayList<>();
            for (Map.Entry<Long, List<MaintenanceAppResponse>> entry : currentTaskMap.entrySet()) {
                taskList.addAll(entry.getValue());
            }
            LinkedList<MaintenanceAppResponse> currentUserTaskList = taskList.stream()
                    .sorted(Comparator.comparing(MaintenanceAppResponse::getPlanDate).reversed()).collect(Collectors.toCollection(LinkedList::new));

            Map<Long, List<MaintenanceAppResponse>> taskMap = page.getRecords().stream().filter(entry ->
                    !Objects.equals(request.getUserId(), entry.getWorkerId1())).collect(Collectors.groupingBy(MaintenanceAppResponse::getLiftId));

            taskList.clear();
            for (Map.Entry<Long, List<MaintenanceAppResponse>> entry : taskMap.entrySet()) {
                taskList.addAll(entry.getValue());
            }
            LinkedList<MaintenanceAppResponse> userTaskList = taskList.stream()
                    .sorted(Comparator.comparing(MaintenanceAppResponse::getPlanDate)).collect(Collectors.toCollection(LinkedList::new));
            currentUserTaskList.addAll(userTaskList);

            page.setRecords(currentUserTaskList);
        }
        return page;
    }

    /**
     * @param request 大修项目id
     * @return RestResponse 电梯列表
     * @description 根据大修项目id查询项目下电梯列表
     * @date 2020/4/15 4:15 下午
     */
    public IPage<ProjectLiftResponse> list(CapitalRepairRequest request) {
        return capitalRepairLiftRelevanceMapper.findListByProjectId(request.getPage(), request);
    }

    /**
     * @param request 公司id
     * @return RestResponse 项目列表
     * @description 根据公司id查询公司下大修项目列表
     * @date 2020/4/20 8:18 下午
     */
    public IPage<ProjectCompanyResponse> capitalProjectList(CapitalRepairRequest request) {
        return capitalRepairLiftRelevanceMapper.findCapitalListByCompanyId(request.getPage(), request);
    }

    /**
     * @param request 用户ID、公司ID
     * @return RestResponse 统计大修项目数量
     * @description 根据用户ID和公司ID统计大修项目数量
     * @date 2020/5/29 3:00 下午
     */
    public CapitalCount countCapitalByUserId(CapitalRepairRequest request) {
        return capitalRepairLiftRelevanceMapper.countCapitalByUserId(request);
    }

    /**
     * @param request 项目id
     * @return RestResponse 项目详情
     * @description 根据项目id查询项目详情
     * @date 2020/4/21 9:13 下午
     */
    public ProjectDetailResponse capitalDetail(CapitalRepairRequest request) {
        ProjectDetailResponse response = capitalRepairLiftRelevanceMapper.findProjectById(request);
        List<ProjectUserResponse> userList = projectUserService.getUserList(request.getId(), request.getMtCompanyId());
        Optional<String> optional = userList.stream().
                filter(entry -> request.getUserId().equals(entry.getUserId())).map(ProjectUserResponse::getIsMonitor).findFirst();
        if (optional.isPresent()) {
            String monitor = optional.get();
            response.setIsMonitor(monitor);
        }
        return response;
    }

}
