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

import cn.com.ty.lift.business.common.CommonRequest;
import cn.com.ty.lift.business.emergency.dto.EmergencyCount;
import cn.com.ty.lift.business.emergency.dto.RepairRequest;
import cn.com.ty.lift.business.emergency.dto.RepairResponse;
import cn.com.ty.lift.business.emergency.entity.EmergencyHistory;
import cn.com.ty.lift.business.emergency.entity.EmergencyRepair;
import cn.com.ty.lift.business.emergency.entity.ErRecordCost;
import cn.com.ty.lift.business.emergency.entity.ErRecordImg;
import cn.com.ty.lift.business.emergency.mapper.EmergencyRepairMapper;
import cn.com.ty.lift.business.evaluation.dao.entity.Evaluation;
import cn.com.ty.lift.business.evaluation.service.EvaluationService;
import cn.com.ty.lift.business.library.dao.entity.PlatformCompanyLiftRelevance;
import cn.com.ty.lift.business.library.service.PlatformCompanyLiftRelevanceService;
import cn.com.ty.lift.common.constants.CommonEnum;
import cn.com.ty.lift.common.utils.ValuePool;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.collection.IterUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

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

/**
 * <p>
 * 临修记录 服务实现类
 * </p>
 *
 * @author wcz
 * @since 2019-12-04
 */
@Service
@AllArgsConstructor
public class EmergencyRepairService extends ServiceImpl<EmergencyRepairMapper, EmergencyRepair> {

    private PlatformCompanyLiftRelevanceService platformCompanyLiftRelevanceService;
    private ErRecordImgService                  erRecordImgService;
    private ErRecordCostService                 erRecordCostService;
    private EvaluationService                   evaluationService;
    private EmergencyHistoryService             emergencyHistoryService;

    /**
     * 分页查询急修中的急修记录
     *
     * @param request RepairRequest
     * @return IPage<RepairResponse>
     */
    public IPage<RepairResponse> pageByRepairing(RepairRequest request) {
        return baseMapper.pageByRepairing(request.getPage(), request);
    }

    /**
     * 根据条件分页查询急修记录
     *
     * @param request RepairRequest
     * @return IPage<RepairResponse>
     */
    public IPage<RepairResponse> pageByCondition(RepairRequest request) {
        //总经理查询所有年检任务
        if (CommonEnum.DefaultRole.HIGH_DIRECTOR.getCode().equals(request.getCurrentRoleCode())) {
            request.setWorkerId(null);
        }
        return baseMapper.pageByCondition(request.getPage(), request);
    }

    public EmergencyCount count(RepairRequest request) {
        return baseMapper.countEmergencyByUserId(request);
    }

    /**
     * 根据条件统计急修记录总条数
     *
     * @param request RepairRequest
     * @return long
     */
    public long countByCondition(RepairRequest request) {
        return baseMapper.countByCondition(request);
    }

    /**
     * 根据id查询急修记录，带关联信息
     *
     * @param id
     * @return RepairResponse
     */
    public RepairResponse infoById(Long id) {
        return baseMapper.infoById(id);
    }

    /**
     * 根据用户id查询关联的急修
     *
     * @param request RepairRequest
     * @return IPage<RepairResponse>
     */
    public IPage<RepairResponse> pageByUser(RepairRequest request) {
        return baseMapper.pageByUser(request.getPage(), request);
    }

    /**
     * 急修接单，修改急修为修理中，修改电梯的业务状态为急修中
     *
     * @param entity RepairRequest
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse taking(EmergencyRepair entity) {
        boolean er = updateById(entity);
        if (!er) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        PlatformCompanyLiftRelevance relevance = platformCompanyLiftRelevanceService.findByMtCompanyAndLift(entity.getMtCompanyId(), entity.getLiftId());
        if (Objects.isNull(relevance)) {
            return RestResponse.fail("平台公司电梯关联信息不存在，请核查");
        }
        //电梯业务状态改成急修中
        relevance.setLiftCompanyStatus(CommonEnum.LiftStatus.EMERGENCY_REPAIR.getCode());
        boolean re = platformCompanyLiftRelevanceService.updateById(relevance);
        if (re) {
            return RestResponse.success(true);
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("修改电梯业务状态失败，请稍后重试");
        }
    }

    /**
     * 根据维保公司和电梯id查找急修
     *
     * @param mtCompanyId 维保公司id
     * @param liftId 电梯id
     * @return EmergencyRepair
     */
    public EmergencyRepair findByMtCompanyAndLift(Long mtCompanyId, Long liftId) {
        this.lambdaQuery();
        LambdaQueryWrapper<EmergencyRepair> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(EmergencyRepair::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(EmergencyRepair::getLiftId, liftId);
        //只查询一条
        lambdaQueryWrapper.last("LIMIT 1");
        return getOne(lambdaQueryWrapper);
    }

    /**
     * 电梯管理中根据电梯，维保公司和项目查询急修记录
     *
     * @param request RepairRequest
     * @return IPage<RepairResponse>
     */
    public IPage<RepairResponse> pageByCompanyLiftProject(RepairRequest request) {
        return baseMapper.pageByLift(request.getPage(), request);
    }

    public List<RepairResponse> listByIdList(RepairRequest request) {
        return baseMapper.listByIdList(request);
    }

    /**
     * 统计维保公司和电梯下是否存在待急修和急修中的急修单
     *
     * @param mtCompanyId 维保公司id
     * @param liftId 电梯id
     * @return int
     */
    public int countRepairing(Long mtCompanyId, Long liftId) {
        LambdaQueryWrapper<EmergencyRepair> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(EmergencyRepair::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(EmergencyRepair::getLiftId, liftId);
        lambdaQueryWrapper.in(EmergencyRepair::getStatus, Arrays.asList(ValuePool.EMERGENCY_STATE_TO_DO, ValuePool.EMERGENCY_STATE_DOING));
        return count(lambdaQueryWrapper);

    }

    public EmergencyRepair findRepairing(Long mtCompanyId, Long liftId, Long projectId) {
        LambdaQueryWrapper<EmergencyRepair> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(EmergencyRepair::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(EmergencyRepair::getLiftId, liftId);
        lambdaQueryWrapper.eq(EmergencyRepair::getProjectId, projectId);
        lambdaQueryWrapper.in(EmergencyRepair::getStatus, Arrays.asList(ValuePool.EMERGENCY_STATE_TO_DO, ValuePool.EMERGENCY_STATE_DOING));
        return getOne(lambdaQueryWrapper);

    }

    private void rollback(){
        //强制手动事务回滚
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }

    /**
     * 开启维保，暂停急修，修改电梯业务状态为维保中
     *
     * @param mtCompanyId 维保公司id
     * @param liftId 电梯id
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse startMaintenance(Long mtCompanyId, Long liftId) {
        // 如果急修单不存在，直接返回，
        EmergencyRepair emergencyRepair = findByMtCompanyAndLift(mtCompanyId, liftId);
        if (Objects.isNull(emergencyRepair)) {
            return RestResponse.success(true);
        }
        //如果存在，不在急修中
        if (emergencyRepair.getStatus() != ValuePool.EMERGENCY_STATE_DOING) {
            return RestResponse.success(true);
        }
        // 如果存在，并且急修中,急修改成暂停中
        emergencyRepair.setStatus(ValuePool.EMERGENCY_STATE_STOPPING);
        boolean er = updateById(emergencyRepair);
        if (!er) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        PlatformCompanyLiftRelevance relevance = platformCompanyLiftRelevanceService.findByMtCompanyAndLift(mtCompanyId, liftId);
        if (Objects.isNull(relevance)) {
            rollback();
            return RestResponse.fail("平台公司电梯关联信息不存在，请核查");
        }
        //电梯业务状态改成维保中
        relevance.setLiftCompanyStatus(CommonEnum.LiftStatus.MAINTENANCE.getCode());
        boolean re = platformCompanyLiftRelevanceService.updateById(relevance);
        if (re) {
            return RestResponse.success(true);
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("修改电梯业务状态失败，请稍后重试");
        }
    }

    /**
     * 停止维保，恢复急修，修改电梯业务状态为急修中
     *
     * @param mtCompanyId 维保公司id
     * @param liftId 电梯id
     * @return boolean
     */
    public RestResponse stopMaintenance(Long mtCompanyId, Long liftId) {
        //如果急修单不存在，直接返回，
        EmergencyRepair emergencyRepair = findByMtCompanyAndLift(mtCompanyId, liftId);
        if (Objects.isNull(emergencyRepair)) {
            return RestResponse.success(true);
        }
        //如果急修单不在暂停中，直接返回true
        if (emergencyRepair.getStatus() != ValuePool.EMERGENCY_STATE_STOPPING) {
            return RestResponse.success(true);
        }
        //恢复暂停中的急修为急修中
        emergencyRepair.setStatus(ValuePool.EMERGENCY_STATE_DOING);
        boolean er = updateById(emergencyRepair);
        if (!er) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        PlatformCompanyLiftRelevance relevance = platformCompanyLiftRelevanceService.findByMtCompanyAndLift(mtCompanyId, liftId);
        if (Objects.isNull(relevance)) {
            rollback();
            return RestResponse.fail("平台公司电梯关联信息不存在，请核查");
        }
        //电梯业务状态改成急修中
        relevance.setLiftCompanyStatus(CommonEnum.LiftStatus.EMERGENCY_REPAIR.getCode());
        boolean re = platformCompanyLiftRelevanceService.updateById(relevance);
        if (re) {
            return RestResponse.success(true);
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("修改电梯业务状态失败，请稍后重试");
        }
    }

    /**
     * 生成急修单，同时插入急修图片记录
     *
     * @param repair EmergencyRepair
     * @param erRecordImgs List<ErRecordImg>
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse repairOrder(EmergencyRepair repair, List<ErRecordImg> erRecordImgs) {
        boolean re = saveOrUpdate(repair);
        if (!re) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        boolean im = erRecordImgService.saveBatch(erRecordImgs, erRecordImgs.size());
        if (im) {
            return RestResponse.success(true);
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("插入急修图片失败，请稍后重试");
        }
    }

    private String formatCostContent(ErRecordCost erRecordCost){
        return String.format("费用项：%s, 应收：%.2f, 实收：%.2f, 开票：%.2f", erRecordCost.getCostName(), erRecordCost.getCostMoney(), erRecordCost.getPayMoney(), erRecordCost.getInvoiceMoney());
    }

    /**
     * 插入急修收费项，同时更新急修记录总金额
     *
     * @param repair
     * @param erRecordCosts
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse addCost(EmergencyRepair repair, List<ErRecordCost> erRecordCosts) {
        boolean re = saveOrUpdate(repair);
        if (!re) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        boolean er = erRecordCostService.saveOrUpdateBatch(erRecordCosts);
        if (er) {
            List<EmergencyHistory> histories = new ArrayList<>();
            for (ErRecordCost erRecordCost : erRecordCosts) {
                EmergencyHistory history = new EmergencyHistory();
                history.setErRecordId(repair.getId());
                history.setOperate("新增收费项");
                history.setDescription(erRecordCost.getCostName());
                history.setBeforeContent("--");
                history.setAfterContent(formatCostContent(erRecordCost));
                history.setOperatorId(repair.getUpdateId());
                history.setOperateDate(LocalDateTime.now());
                histories.add(history);
            }
            boolean his = emergencyHistoryService.saveOrUpdateBatch(histories, histories.size());
            if(his){
                return RestResponse.success(true);
            }else{
                rollback();
                return RestResponse.fail("插入急修操作记录失败，请稍后重试");
            }
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("插入急修收费项失败，请稍后重试");
        }
    }

    /**
     * 修改收费项，更新急修总金额
     *
     * @param repair EmergencyRepair
     * @param erRecordCosts List<ErRecordCost>
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse modifyCost(EmergencyRepair repair,List<ErRecordCost> oldRecordCosts, List<ErRecordCost> erRecordCosts) {
        boolean re = saveOrUpdate(repair);
        if (!re) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        List<ErRecordCost> updateList = new ArrayList<>();
        List<ErRecordCost> deleteList = new ArrayList<>();
        List<EmergencyHistory> histories = new ArrayList<>();
        //新增的收费项
        List<ErRecordCost> insertList = erRecordCosts.stream().filter(cost -> Objects.isNull(cost.getId())).collect(Collectors.toList());
        if (IterUtil.isNotEmpty(insertList)) {
            for (ErRecordCost erRecordCost : insertList) {
                EmergencyHistory history = new EmergencyHistory();
                history.setErRecordId(repair.getId());
                history.setDescription(erRecordCost.getCostName());
                history.setBeforeContent("--");
                String afterContent = formatCostContent(erRecordCost);
                history.setAfterContent(afterContent);
                history.setOperatorId(repair.getUpdateId());
                history.setOperateDate(LocalDateTime.now());
                history.setOperate("新增收费项");
                histories.add(history);
            }
        }
        //比较原有的收费项
        for (ErRecordCost oldRecordCost : oldRecordCosts) {
            EmergencyHistory history = new EmergencyHistory();
            history.setErRecordId(repair.getId());
            history.setDescription(oldRecordCost.getCostName());
            String before = formatCostContent(oldRecordCost);
            history.setBeforeContent(before);
            history.setOperatorId(repair.getUpdateId());
            history.setOperateDate(LocalDateTime.now());
            Optional<ErRecordCost> original = erRecordCosts.stream().filter(cost -> oldRecordCost.getId().equals(cost.getId())).findFirst();
            if (original.isPresent()) {
                history.setOperate("修改收费项");
                String after = formatCostContent(original.get());
                if (!Objects.equals(before, after)) {
                    history.setAfterContent(after);
                    histories.add(history);
                    updateList.add(oldRecordCost);
                }
            } else {
                history.setOperate("删除收费项");
                history.setAfterContent("--");
                histories.add(history);
                deleteList.add(oldRecordCost);
            }
        }
        if(IterUtil.isNotEmpty(deleteList)){
            boolean delete = erRecordCostService.removeByIds(deleteList.stream().map(ErRecordCost::getId).collect(Collectors.toList()));
            if(!delete){
                rollback();
                return RestResponse.fail("删除急修收费项失败，请稍后重试");
            }
        }
        if(IterUtil.isNotEmpty(updateList)){
            boolean update = erRecordCostService.updateBatchById(updateList, updateList.size());
            if(!update){
                rollback();
                return RestResponse.fail("修改急修收费项失败，请稍后重试");
            }
        }
        if(IterUtil.isNotEmpty(insertList)){
            boolean save = erRecordCostService.saveBatch(insertList, insertList.size());
            if(!save){
                rollback();
                return RestResponse.fail("新增急修收费项失败，请稍后重试");
            }
        }
        boolean his = emergencyHistoryService.saveBatch(histories, histories.size());
        if(his){
            return RestResponse.success(true);
        }else{
            rollback();
            return RestResponse.fail("插入急修操作记录失败，请稍后重试");
        }
    }

    /**
     * 删除收费项，修改急修中的总金额
     *
     * @param repair EmergencyRepair
     * @param erRecordCost ErRecordCost
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse deleteCost(EmergencyRepair repair, ErRecordCost erRecordCost) {
        boolean er = erRecordCostService.removeById(erRecordCost.getId());
        if (!er) {
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        boolean re = updateById(repair);
        if (re) {
            EmergencyHistory history = new EmergencyHistory();
            history.setErRecordId(repair.getId());
            history.setOperate("删除收费项");
            history.setDescription(erRecordCost.getCostName());
            history.setBeforeContent(formatCostContent(erRecordCost));
            history.setAfterContent("--");
            history.setOperatorId(repair.getUpdateId());
            history.setOperateDate(LocalDateTime.now());
            boolean his = emergencyHistoryService.save(history);
            if(his){
                return RestResponse.success(true);
            }else{
                rollback();
                return RestResponse.fail("插入急修操作记录失败，请稍后重试");
            }
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("删除急修收费项失败，请稍后重试");
        }
    }

    /**
     * 急修评价，同时更新急修的评价状态
     *
     * @param repair EmergencyRepair
     * @param entity Evaluation
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse evaluate(EmergencyRepair repair, Evaluation entity) {
        boolean ev = evaluationService.save(entity);
        if (!ev) {
            return RestResponse.fail("插入评价失败，请稍后重试");
        }
        boolean re = updateById(repair);
        if (re) {
            return RestResponse.success(true);
        } else {
            //强制手动事务回滚
            rollback();
            return RestResponse.fail("更新急修评价状态失败，请稍后重试");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public RestResponse close(EmergencyRepair repair){
        boolean er = updateById(repair);
        if(!er){
            return RestResponse.fail("修改急修失败，请稍后重试");
        }
        PlatformCompanyLiftRelevance relevance = platformCompanyLiftRelevanceService.findByMtCompanyAndLift(repair.getMtCompanyId(), repair.getLiftId());
        if (Objects.isNull(relevance)) {
            return RestResponse.fail("平台公司电梯关联信息不存在，请核查");
        }
        //电梯业务状态如果在急修中 改成正常
        if(relevance.getLiftCompanyStatus().equals(CommonEnum.LiftStatus.EMERGENCY_REPAIR.getCode())){
            relevance.setLiftCompanyStatus(CommonEnum.LiftStatus.NORMAL.getCode());
            boolean re = platformCompanyLiftRelevanceService.updateById(relevance);
            if (!re) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("修改电梯业务状态失败，请稍后重试");
            }
        }
        return RestResponse.success(true);
    }

    public long countDoingByUser(CommonRequest request){
        return baseMapper.countDoingByUser(request);
    }
}
