/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.depotWorkAlarm.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.biz.core.Const.BizStr;
import vip.xiaonuo.biz.modular.depotAlarm.param.DepotAlarmAddParam;
import vip.xiaonuo.biz.modular.depotAlarm.service.DepotAlarmService;
import vip.xiaonuo.biz.modular.depotGrain.service.DepotGrainService;
import vip.xiaonuo.biz.modular.depotTruckBook.service.DepotTruckBookService;
import vip.xiaonuo.biz.modular.depotTruckLade.service.DepotTruckLadeService;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.biz.modular.depotWorkAlarm.entity.DepotWorkAlarm;
import vip.xiaonuo.biz.modular.depotWorkAlarm.mapper.DepotWorkAlarmMapper;
import vip.xiaonuo.biz.modular.depotWorkAlarm.param.DepotWorkAlarmAddParam;
import vip.xiaonuo.biz.modular.depotWorkAlarm.param.DepotWorkAlarmEditParam;
import vip.xiaonuo.biz.modular.depotWorkAlarm.param.DepotWorkAlarmIdParam;
import vip.xiaonuo.biz.modular.depotWorkAlarm.param.DepotWorkAlarmPageParam;
import vip.xiaonuo.common.prop.CommonProperties;
import vip.xiaonuo.common.util.DatesUtil;
import vip.xiaonuo.dev.api.DevFileApi;
import vip.xiaonuo.dev.modular.file.util.MultipartFileUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 出入库异常Service接口实现类
 *
 * @author xiang
 * @date 2023/09/18 11:09
 **/
@Service
public class DepotWorkAlarmService extends ServiceImpl<DepotWorkAlarmMapper, DepotWorkAlarm> {

    @Resource
    DepotGrainService depotGrainService;
    @Resource
    DepotTruckBookService depotTruckBookService;
    @Resource
    private DepotTruckLadeService depotTruckLadeService;
    @Resource
    DepotAlarmService alarmService;
    @Resource
    DevFileApi devFileApi;
    @Resource
    private CommonProperties commonProperties;

    public Page<DepotWorkAlarm> page(DepotWorkAlarmPageParam param) {
        QueryWrapper<DepotWorkAlarm> wrapper = new QueryWrapper<>();
        List<String> depotIdLst = depotGrainService.lstOrgGrep();
        wrapper.lambda().in(CollUtil.isNotEmpty(depotIdLst), DepotWorkAlarm::getDepotId, depotIdLst);
        wrapper.and(Strings.isNotBlank(param.getSearchKey()), w ->
                w.lambda().like(DepotWorkAlarm::getLicensePlate, param.getSearchKey())
                        .or().like(DepotWorkAlarm::getAlarmMsg, param.getSearchKey())
                        .or().like(DepotWorkAlarm::getSaveMsg, param.getSearchKey()));
        if (ObjectUtil.isNotEmpty(param.getDepotId()))
            wrapper.lambda().eq(DepotWorkAlarm::getDepotId, param.getDepotId());
        if (ObjectUtil.isNotEmpty(param.getDepotBizType()))
            wrapper.lambda().eq(DepotWorkAlarm::getDepotBizType, param.getDepotBizType());
        if (ObjectUtil.isNotEmpty(param.getLicensePlate()))
            wrapper.lambda().like(DepotWorkAlarm::getLicensePlate, param.getLicensePlate());
        if (ObjectUtil.isNotEmpty(param.getSaveState()))
            wrapper.lambda().eq(DepotWorkAlarm::getSaveState, param.getSaveState());
        if (ObjectUtil.isNotEmpty(param.getAlarmMsg()))
            wrapper.lambda().like(DepotWorkAlarm::getAlarmMsg, param.getAlarmMsg());
        wrapper.lambda().like(Strings.isNotBlank(param.getAlarmType()), DepotWorkAlarm::getAlarmType, param.getAlarmType());
        wrapper.lambda().like(Strings.isNotBlank(param.getProcessMsg()), DepotWorkAlarm::getAlarmMsg, param.getProcessMsg());
        if (ObjectUtil.isAllNotEmpty(param.getSortField(), param.getSortOrder())) {
            CommonSortOrderEnum.validate(param.getSortOrder());
            wrapper.orderBy(true, param.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(param.getSortField()));
        } else {
            wrapper.lambda().orderByDesc(DepotWorkAlarm::getId);
        }
        Page page = this.page(CommonPageRequest.defaultPage(), wrapper);
        //匹配粮库名称
        depotGrainService.putDepotName(page.getRecords());
        //匹配完整图片地址
        putPicUrl(page.getRecords());
        return page;
    }

    /**
     * 匹配完整图片地址
     *
     * @author xiang
     * @date 2023/09/27 19:31
     **/
    public void putPicUrl(List<DepotWorkAlarm> list) {
        list.forEach(one -> {
            if (Strings.isNotBlank(one.getSavePicUrl()))
                one.setSavePicUrl(commonProperties.getBackendUrl() + one.getSavePicUrl());
        });
    }

    public List<DepotWorkAlarm> lst(DepotWorkAlarm param) {
        return list(new LambdaUpdateWrapper<>(param));
    }

    public DepotWorkAlarm getOne(DepotWorkAlarm param) {
        LambdaUpdateWrapper<DepotWorkAlarm> wrapper = new LambdaUpdateWrapper<>(param);
        wrapper.orderByDesc(DepotWorkAlarm::getCreateTime);
        return getOne(wrapper.last("limit 1"));
    }

    //待处理的报警
    public boolean existAlarmIn(String depotId, String plate, String alarmType, String flowType) {
        DepotWorkAlarm alarm = new DepotWorkAlarm(depotId, plate, alarmType, flowType, BizStr.STATE_PROCESS_N);
        return !list(new LambdaUpdateWrapper<>(alarm)).isEmpty();
    }

    public DepotWorkAlarm add(DepotWorkAlarmAddParam param) {
        DepotWorkAlarm one = BeanUtil.toBean(param, DepotWorkAlarm.class);
        DepotAlarmAddParam alarmAddParam = new DepotAlarmAddParam(param.getDepotId(), BizStr.ALARM_CHU_RU_KU
                , StringUtils.join(param.getLicensePlate(), param.getDepotBizType(), param.getAlarmType(), "，", param.getAlarmMsg()));
        //异常
        if (BizStr.ALARM_TYPE_Y.equals(one.getAlarmType())) {
            one.setSaveState(BizStr.STATE_PROCESS_Y);
            one.setSaveTime(DatesUtil.forDateTime());
            one.setSaveMsg("自动处理异常。");
            alarmAddParam.setSaveState(one.getSaveState());
        }
        alarmService.add(alarmAddParam);
        one.setUnionAlarmId(alarmAddParam.getId());
        this.save(one);
        return one;
    }

    public void edit(DepotWorkAlarmEditParam depotWorkAlarmEditParam) {
        DepotWorkAlarm depotWorkAlarm = this.queryEntity(depotWorkAlarmEditParam.getId());
        BeanUtil.copyProperties(depotWorkAlarmEditParam, depotWorkAlarm);
        this.updateById(depotWorkAlarm);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(List<DepotWorkAlarmIdParam> depotWorkAlarmIdParamList) {
        List<String> ids = CollStreamUtil.toList(depotWorkAlarmIdParamList, DepotWorkAlarmIdParam::getId);
        List<DepotWorkAlarm> alarms = listByIds(ids);
        // 联动删除
        alarmService.deleteByIds(CollStreamUtil.toList(alarms, DepotWorkAlarm::getUnionAlarmId));
        // 执行删除
        this.removeBatchByIds(ids);
    }

    public DepotWorkAlarm detail(DepotWorkAlarmIdParam depotWorkAlarmIdParam) {
        return this.queryEntity(depotWorkAlarmIdParam.getId());
    }

    public DepotWorkAlarm queryEntity(String id) {
        DepotWorkAlarm depotWorkAlarm = this.getById(id);
        if (ObjectUtil.isEmpty(depotWorkAlarm)) {
            throw new CommonException("出入库异常不存在，id值为：{}", id);
        }
        return depotWorkAlarm;
    }

    /**
     * 处理
     *
     * @author xiang
     * @date 2023/09/19 13:59
     **/
    @Transactional(rollbackFor = Exception.class)
    public void processTo(DepotWorkAlarm param) {
        DepotWorkAlarm one = getById(param.getId());
        one.setSaveState(param.getSaveState());
        one.setSaveMsg(param.getSaveMsg());
        //处理图片
        if (Strings.isNotBlank(param.getSavePicUrl()) && !Objects.equals(param.getSavePicUrl(), one.getSavePicUrl())) {
            if (param.getSavePicUrl().length() != 19)
                param.setSavePicUrl(devFileApi.storageFileWithReturnIdLocal(MultipartFileUtils.base64ToMultipart(param.getSavePicUrl())));
            if (param.getSavePicUrl().length() == 19)
                param.setSavePicUrl(devFileApi.storageFilePathReturnUrlById(param.getSavePicUrl()));
        }
        one.setSavePicUrl(param.getSavePicUrl());
        one.setSaveTime(DatesUtil.forDateTime());
        one.setSaveUser(StpLoginUserUtil.getLoginUser().getName());
        //驳回离场/允许通行
        if (BizStr.STATE_TRUCK_G.equals(param.getSaveState())
                || (BizStr.STATE_TRUCK_Y.equals(param.getSaveState()) && checkOnlyOne(param.getId(), one.getTruckBookId()))) {
            depotTruckBookService.processTo(one.getTruckBookId(), param.getSaveState());
        }
        //卸货超时时间更新
        if (BizStr.STATE_TRUCK_Y.equals(param.getSaveState()) && "21".equals(one.getFlowType())) {
            depotTruckLadeService.editLimitInTimeByBookId(one.getTruckBookId(), null, null, DatesUtil.forDateTime(DatesUtil.addDay(new Date(), 1)));
        }
        updateById(one);
        alarmService.processById(one.getUnionAlarmId(), one.getSaveState());
    }

    /**
     * 检查车辆唯一待处理报警
     *
     * @author xiang
     * @date 2023/09/19 13:59
     **/
    @Transactional(rollbackFor = Exception.class)
    public boolean checkOnlyOne(String id, String bookId) {
        LambdaQueryWrapper<DepotWorkAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(DepotWorkAlarm::getId, id);
        wrapper.eq(DepotWorkAlarm::getTruckBookId, bookId);
        wrapper.eq(DepotWorkAlarm::getAlarmType, BizStr.ALARM_TYPE_B);
        wrapper.eq(DepotWorkAlarm::getSaveState, BizStr.STATE_PROCESS_N);
        return count(wrapper) == 0;
    }

}
