package cn.wise.sc.acquisition.business.service.impl;

import cn.wise.sc.acquisition.business.constant.Rcode;
import cn.wise.sc.acquisition.business.entity.TProcessesBlastdesignHole;
import cn.wise.sc.acquisition.business.entity.TProcessesBlastdesignVolume;
import cn.wise.sc.acquisition.business.enumation.ProjectEnum;
import cn.wise.sc.acquisition.business.mapper.TProcessesBlastdesignHoleMapper;
import cn.wise.sc.acquisition.business.model.query.TProcessesBlastQuery;
import cn.wise.sc.acquisition.business.model.query.TProcessesBlastdesignHoleQuery;
import cn.wise.sc.acquisition.business.model.query.TProcessesBlastdesignVolumeQuery;
import cn.wise.sc.acquisition.business.model.query.TProcessesDrillingQuery;
import cn.wise.sc.acquisition.business.model.vo.TProcessesProductVo;
import cn.wise.sc.acquisition.business.model.vo.TProcessesBlastdesignHoleVo;
import cn.wise.sc.acquisition.business.service.*;
import cn.wise.sc.acquisition.business.util.BeanUtilsNewCopy;
import cn.wise.sc.acquisition.business.util.DateUtil;
import cn.wise.sc.acquisition.business.wrapper.page.Query;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author renchao
 * @since 2021-04-27
 */
@Slf4j
@Service
public class TProcessesBlastdesignHoleServiceImpl extends ServiceImpl<TProcessesBlastdesignHoleMapper, TProcessesBlastdesignHole> implements ITProcessesBlastdesignHoleService {

    @Autowired
    private ITProcessesBlastdesignVolumeService itProcessesBlastdesignVolumeService;

    @Autowired
    private ITProcessesDrillingService itProcessesDrillingService;

    @Autowired
    private ITProcessesBlastService itProcessesBlastService;

    @Autowired
    private ITSysDictService itSysDictService;

    @Override
    public R getPage(TProcessesBlastdesignHoleQuery tProcessesBlastdesignHoleQuery, Query query) {
        log.info(JSON.toJSONString(tProcessesBlastdesignHoleQuery));
        //参数校验
        //分页
        Page<TProcessesBlastdesignHole> page = new Page<>(query.getPageNum(), query.getPageSize());
        //条件封装
        QueryWrapper<TProcessesBlastdesignHole> queryWrapper = new QueryWrapper<>();
        //如果设计时间不为空 因为涉及到表连接，需要创建字段别名
        if (tProcessesBlastdesignHoleQuery.getDesignDate() != null) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(ProjectEnum.TableAlias.B.getLabel()).append(ProjectEnum.TProcessesBlastdesignVolume.DESIGN_DATE.getLabel());
            //前端传来的时间可能为2021-04-05 17:37:33.000, 需要查询 2021-04-05 00:00:00 到 2021-04-05 23:59:59 的数据 故作处理
            queryWrapper
                    .ge(stringBuilder.toString(), DateUtil.getBeginTimeStr(tProcessesBlastdesignHoleQuery.getDesignDate()))
                    .le(stringBuilder.toString(), DateUtil.getEndTimeStr(tProcessesBlastdesignHoleQuery.getDesignDate()));
        }
        //查询分页数据
        Page<TProcessesBlastdesignHoleVo> data = baseMapper.getPage(page, queryWrapper);
        //查询，根据筛选条件的总条数的孔深合计，不分页 孔深合计 表连接sql需要 a.字段
        Double depthSum = baseMapper.getSumByCondition(new StringBuffer()
                .append(ProjectEnum.TableAlias.A.getLabel())
                .append(ProjectEnum.TProcessesBlastdesignVolume.DEPTH.getLabel()).toString(), queryWrapper);
        return R.ok(new TProcessesProductVo<>(data, depthSum));
    }


    @Override
    public R updateByUid(TProcessesBlastdesignHoleQuery query) {
        log.info(JSON.toJSONString(query));
        //参数校验
        Rcode.NOT_PARAM.assertNotNull(query);
        Rcode.NOT_PARAM.assertNotNull(query.getUid());
        //判断数据是否存在
        TProcessesBlastdesignHole temp = baseMapper.selectById(query.getUid());
        if (temp == null) {
            return R.failed("炮孔设计中->数据不存在：uid：" + query.getUid());
        }
        //判断炮孔编号是否存在
        if (StringUtils.isNotBlank(query.getBlastHoleID()) && !temp.getBlastHoleID().equals(query.getBlastHoleID())) {
            R r = getByBlastHoleID(query);
            if (r.getData() != null) {
                return R.failed("炮孔设计中->炮孔编号已存在: BlastHoleID:" + query.getBlastHoleID());
            }
//            //修改穿孔工序炮孔编号
//            TProcessesDrillingQuery tProcessesDrillingQuery = new TProcessesDrillingQuery();
//            tProcessesDrillingQuery.setUid(temp.getUid());
//            tProcessesDrillingQuery.setNewHoleID(query.getBlastHoleID());
//            R r1 = itProcessesDrillingService.updateByUid(tProcessesDrillingQuery);
//            if (r1.getCode() != 0) {
//                log.error("炮孔设计中->修改穿孔工序炮孔编号失败：{}", JSON.toJSONString(tProcessesDrillingQuery));
//                return R.failed(r1.getMsg());
//            }
//            //修改爆破设计炮孔编号
//            TProcessesBlastQuery tProcessesBlastQuery = new TProcessesBlastQuery();
//            tProcessesBlastQuery.setUid(temp.getUid());
//            tProcessesBlastQuery.setNewHoleID(query.getBlastHoleID());
//            R r2 = itProcessesBlastService.updateByUid(tProcessesBlastQuery);
//            if (r2.getCode() != 0) {
//                log.error("炮孔设计中->修改爆破设计炮孔编号失败：{}", JSON.toJSONString(tProcessesBlastQuery));
//                return R.failed(r2.getMsg());
//            }
        }
        //判断是否需要修改关联的 设计爆区爆破量
        if (StringUtils.isNotBlank(query.getStepName())
                || StringUtils.isNotBlank(query.getBlastAreaName())
                || StringUtils.isNotBlank(query.getStopeName())) {
            //判断设计爆区爆破量是否存在数据 不存在不能修改
            //query里不一定StopeName,StepName,BlastAreaName都有，需要从temp中拿query没有的，
            // 所以将query有的更新到temp中，再把temp中的复制到tMineStopeQuery
            BeanUtilsNewCopy.copyPropertiesIgnoreNull(query, temp);
            TProcessesBlastdesignVolumeQuery tProcessesBlastdesignVolumeQuery = new TProcessesBlastdesignHoleQuery();
            BeanUtils.copyProperties(temp, tProcessesBlastdesignVolumeQuery);
            R volume = itProcessesBlastdesignVolumeService.getByQuery(tProcessesBlastdesignVolumeQuery);
            if (volume.getData() == null) {
                return R.failed("炮孔设计中->设计爆区爆破量表数据不存在，StopeName,StepName,BlastAreaName");
            }
        }
        //条件封装
        //如果修改了孔距，排距，台阶高度 需要重新计算单孔爆破量， 单孔爆破量(m3)=孔距*排距*台阶高度
        //所以直接copy上面根据uid查出来的数据 copy ->非空值<- 将query的值更新到查出来的对象上 进行计算并更新到数据库即可
        BeanUtilsNewCopy.copyPropertiesIgnoreNull(query, temp);
        //判断是否修改设计爆区爆破量 的设计日期，或者设计爆区爆破量(m3)  TAT
        if (query.getDesignDate() != null || query.getBlastVolume() != null) {
            TProcessesBlastdesignVolumeQuery tProcessesBlastdesignVolumeQuery = new TProcessesBlastdesignHoleQuery();
            tProcessesBlastdesignVolumeQuery.setStopeName(temp.getStopeName());
            tProcessesBlastdesignVolumeQuery.setStepName(temp.getStepName());
            tProcessesBlastdesignVolumeQuery.setBlastAreaName(temp.getBlastAreaName());
            tProcessesBlastdesignVolumeQuery.setDesignDate(query.getDesignDate());
            tProcessesBlastdesignVolumeQuery.setBlastVolume(query.getBlastVolume());
            R r = itProcessesBlastdesignVolumeService.updateByQuery(tProcessesBlastdesignVolumeQuery);
            if (r.getCode() != 0) {
                log.error("炮孔设计中->修改设计爆区爆破量失败:" + JSON.toJSONString(tProcessesBlastdesignVolumeQuery));
                return R.failed(r.getMsg());
            }
        }
        //判断是否需要重新计算爆破量
        if (query.getHoleSpace() != null
                || query.getRowSpace() != null
                || query.getStepHeight() != null) {
            //计算单孔爆破量
            calculateHoleBlastVolume(temp);
        }
        //如果修改了台阶高度，需要通知爆破设计重新计算设计区爆破量
        if (query.getStepHeight() != null) {
            TProcessesDrillingQuery tProcessesDrillingQuery = new TProcessesDrillingQuery();
            tProcessesDrillingQuery.setUid(temp.getUid());
            tProcessesDrillingQuery.setStepHeight(query.getStepHeight());
            itProcessesDrillingService.updateHoleBlastVolume(tProcessesDrillingQuery);
        }
        QueryWrapper<TProcessesBlastdesignHole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ProjectEnum.TProcessesBlastdesignHole.UID.getLabel(), query.getUid());
        //修改
        int update = baseMapper.update(temp, queryWrapper);
        if (update > 0) {
            return R.ok("炮孔设计中->修改成功");
        } else {
            log.info(JSON.toJSONString(temp));
            return R.failed("炮孔设计中->修改失败");
        }
    }

    @Override
    public R updateByBlastHoleID(TProcessesBlastdesignHoleQuery query) {
        log.info(JSON.toJSONString(query));
        //参数校验
        Rcode.NOT_PARAM.assertNotNull(query);
        Rcode.NOT_PARAM.assertNotNull(query.getBlastHoleID());
        //判断数据炮孔设计是否存在
        //判断数据是否存在
        QueryWrapper<TProcessesBlastdesignHole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ProjectEnum.TProcessesBlastdesignHole.BLAST_HOLE_ID.getLabel(), query.getBlastHoleID());

        TProcessesBlastdesignHole temp = baseMapper.selectOne(queryWrapper);
        if (temp == null) {
            return R.failed("炮孔设计中->数据不存在：BLAST_HOLE_ID：" + query.getBlastHoleID());
        }
        //判断是否将炮孔编号修改为新的炮孔编号 如果是，直接修改，不能调用基础方法，避免循环
        if (StringUtils.isNotBlank(query.getNewBlastHoleID())) {
            temp.setBlastHoleID(query.getNewBlastHoleID());
            int update = baseMapper.updateById(temp);
            if (update > 0) {
                return R.ok("炮孔设计中->修改成功");
            } else {
                return R.failed("炮孔设计中->修改失败");
            }
        }

        query.setUid(temp.getUid());
        //调用基础方法修改
        return updateByUid(query);
    }


    @Override
    public R deleteByUid(TProcessesBlastdesignHoleQuery query) {
        log.info(JSON.toJSONString(query));
        //参数校验
        Rcode.NOT_PARAM.assertNotNull(query);
        Rcode.NOT_PARAM.assertNotEmpty(query.getUid());
        TProcessesBlastdesignHole temp = baseMapper.selectById(query.getUid());
        if (temp == null) {
            return R.failed("炮孔设计中->数据不存在，uid：" + query.getUid());
        }
        //删除
        int delete = baseMapper.delete(new QueryWrapper<TProcessesBlastdesignHole>().eq(ProjectEnum.TProcessesBlastdesignHole.UID.getLabel(), query.getUid()));
        if (delete > 0) {
            return R.ok("炮孔设计中->删除成功");
        } else {
            return R.failed("炮孔设计中->删除失败");
        }

    }

    @Override
    @Transactional
    public R insertTProcessesBlastdesignHole(TProcessesBlastdesignHoleQuery query) {
        log.info(JSON.toJSONString(query));
        //参数校验
        Rcode.NOT_PARAM.assertNotNull(query);
        Rcode.NOT_PARAM.assertNotEmpty(query.getStopeName());
        Rcode.NOT_PARAM.assertNotEmpty(query.getStepName());
        Rcode.NOT_PARAM.assertNotEmpty(query.getBlastAreaName());
        Rcode.NOT_PARAM.assertNotEmpty(query.getBlastHoleID());
        Rcode.NOT_PARAM.assertNotNull(query.getDepth());
        Rcode.NOT_PARAM.assertNotNull(query.getRowSpace());
        Rcode.NOT_PARAM.assertNotNull(query.getHoleSpace());
        Rcode.NOT_PARAM.assertNotNull(query.getAzimuth());
        Rcode.NOT_PARAM.assertNotNull(query.getInclination());
        Rcode.NOT_PARAM.assertNotNull(query.getAperture());
        Rcode.NOT_PARAM.assertNotNull(query.getStepHeight());
        Rcode.NOT_PARAM.assertNotNull(query.getX());
        Rcode.NOT_PARAM.assertNotNull(query.getY());
        Rcode.NOT_PARAM.assertNotNull(query.getZ());
        Rcode.NOT_PARAM.assertNotNull(query.getDrillingDate());
        //uid自动生成 不能手动设置
        if (query.getUid() != null) {
            return R.failed("炮孔设计中->uid自动生成 不能手动设置");
        }
        //tag为自动生成不能添加
        if (StringUtils.isNotBlank(query.getTag())) {
            return R.failed("炮孔设计中->tag为自动生成不能添加");
        }
        //判断炮孔编号是否存在
        if (StringUtils.isNotBlank(query.getBlastHoleID())) {
            R r = getByBlastHoleID(query);
            if (r.getData() != null) {
                return R.failed("炮孔设计中->炮孔编号已存在: BlastHoleID:" + query.getBlastHoleID());
            }
        }
        //查看设计爆区爆破量是否存在数据
        TProcessesBlastdesignVolumeQuery tProcessesBlastdesignVolumeQuery = new TProcessesBlastdesignHoleQuery();
        BeanUtils.copyProperties(query, tProcessesBlastdesignVolumeQuery);
        R r = itProcessesBlastdesignVolumeService.getByQuery(tProcessesBlastdesignVolumeQuery);
        if (r.getData() == null) {
            return R.failed("炮孔设计中->设计爆区爆破量表数据不存在，StopeName,StepName,BlastAreaName");
        }

        //条件封装
        TProcessesBlastdesignHole tProcessesBlastdesignHole = new TProcessesBlastdesignHole();
        BeanUtils.copyProperties(query, tProcessesBlastdesignHole);
        //设置设计日期
        TProcessesBlastdesignVolume volume = (TProcessesBlastdesignVolume) r.getData();
        if (volume.getDesignDate() == null) {
            log.error("炮孔设计中->设计爆区爆破量表数据中设计日期为空:{}", JSON.toJSONString(volume));
            return R.failed("炮孔设计中->设计爆区爆破量表数据中设计日期为空:" + JSON.toJSONString(volume));
        }
        tProcessesBlastdesignHole.setDesignDate(volume.getDesignDate());
        //单孔爆破量(m3)=孔距*排距*台阶高度
        calculateHoleBlastVolume(tProcessesBlastdesignHole);
        //设置tag
        R tagDate = itSysDictService.getTagDate(null);
        if (tagDate.getCode() != 0) {
            return R.failed(tagDate.getMsg());
        }
        tProcessesBlastdesignHole.setTag((String) tagDate.getData());
        //增加
        log.info(JSON.toJSONString(tProcessesBlastdesignHole));
        int insert = baseMapper.insert(tProcessesBlastdesignHole);
        if (insert > 0) {
            R r0 = getByBlastHoleID(query);
            TProcessesBlastdesignHole hole = (TProcessesBlastdesignHole) r0.getData();
            //增加一条穿孔工序
            TProcessesDrillingQuery tProcessesDrillingQuery = new TProcessesDrillingQuery();
            tProcessesDrillingQuery.setUid(hole.getUid());
            //tProcessesDrillingQuery.setTag(DateUtil.timeToStr(LocalDateTime.now(), DateUtil.FORMAT_TO_SECOND));
            R r1 = itProcessesDrillingService.insertTProcessesDrilling(tProcessesDrillingQuery);
            if (r1.getCode() != 0) {
                log.error("炮孔设计中->增加一条穿孔工序失败:" + JSON.toJSONString(tProcessesDrillingQuery));
                return R.failed(r1.getMsg());
            }

            //增加一条爆破工序
            TProcessesBlastQuery tProcessesBlastQuery = new TProcessesBlastQuery();
            tProcessesBlastQuery.setUid(hole.getUid());
            //tProcessesBlastQuery.setTag(DateUtil.timeToStr(LocalDateTime.now(), DateUtil.FORMAT_TO_SECOND));
            R r2 = itProcessesBlastService.insertTProcessesBlast(tProcessesBlastQuery);
            if (r2.getCode() != 0) {
                log.error("炮孔设计中->增加一条爆破工序失败:" + JSON.toJSONString(tProcessesBlastQuery));
                return R.failed(r2.getMsg());
            }
            return R.ok("炮孔设计中->增加成功");
        } else {
            log.error(JSON.toJSONString(tProcessesBlastdesignHole));
            return R.failed("炮孔设计中->增加失败");
        }
    }

    @Override
    public R getByUid(TProcessesBlastdesignHoleQuery query) {
        log.info(JSON.toJSONString(query));
        //参数校验
        Rcode.NOT_PARAM.assertNotNull(query);
        Rcode.NOT_PARAM.assertNotEmpty(query.getUid());
        //条件
        QueryWrapper<TProcessesBlastdesignHole> queryWrapper = new QueryWrapper<>();
        StringBuilder uid = new StringBuilder();
        uid.append(ProjectEnum.TableAlias.A.getLabel()).append(ProjectEnum.TProcessesBlastdesignHole.UID.getLabel());
        queryWrapper.eq(uid.toString(), query.getUid());
        //查询并且返回
        return R.ok(baseMapper.getByQuery(queryWrapper));
    }


    @Override
    public R getByBlastHoleID(TProcessesBlastdesignHoleQuery query) {
        log.info(JSON.toJSONString(query));
        //参数校验
        Rcode.NOT_PARAM.assertNotNull(query);
        Rcode.NOT_PARAM.assertNotEmpty(query.getBlastHoleID());
        //封装
        QueryWrapper<TProcessesBlastdesignHole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ProjectEnum.TProcessesBlastdesignHole.BLAST_HOLE_ID.getLabel(), query.getBlastHoleID());
        //查询并且返回
        return R.ok(baseMapper.selectOne(queryWrapper));
    }

    /**
     * 计算并设值 单孔爆破量(m3)=孔距*排距*台阶高度
     */
    private void calculateHoleBlastVolume(TProcessesBlastdesignHole tProcessesBlastdesignHole) {
        tProcessesBlastdesignHole.setHoleBlastVolume(tProcessesBlastdesignHole.getHoleSpace()
                * tProcessesBlastdesignHole.getRowSpace()
                * tProcessesBlastdesignHole.getStepHeight());
    }
}
