/*
 * 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.depotGrain.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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.biz.api.wxapp.service.CreateWxaQrCodeService;
import vip.xiaonuo.biz.core.Const.BizStr;
import vip.xiaonuo.biz.core.exception.BizExceptionEnum;
import vip.xiaonuo.biz.modular.depotAlarm.param.DepotAlarmAddParam;
import vip.xiaonuo.biz.modular.depotAlarm.service.DepotAlarmService;
import vip.xiaonuo.biz.modular.depotGrain.entity.BaseDepotGrainName;
import vip.xiaonuo.biz.modular.depotGrain.entity.DepotGrain;
import vip.xiaonuo.biz.modular.depotGrain.mapper.DepotGrainMapper;
import vip.xiaonuo.biz.modular.depotGrain.param.DepotGrainAddParam;
import vip.xiaonuo.biz.modular.depotGrain.param.DepotGrainEditParam;
import vip.xiaonuo.biz.modular.depotGrain.param.DepotGrainIdParam;
import vip.xiaonuo.biz.modular.depotGrain.param.DepotGrainPageParam;
import vip.xiaonuo.biz.modular.sysUserWxOpenSendLog.service.SysUserWxOpenSendLogService;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.common.prop.CommonProperties;
import vip.xiaonuo.common.util.DatesUtil;
import vip.xiaonuo.common.util.HexUtils;
import vip.xiaonuo.dev.api.DevFileApi;
import vip.xiaonuo.dev.modular.file.util.MultipartFileUtils;
import vip.xiaonuo.sys.api.SysUserApi;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 粮库表Service接口
 *
 * @author xiang
 * @date 2023/09/12 15:06
 **/
@Service
public class DepotGrainService extends ServiceImpl<DepotGrainMapper, DepotGrain> {

    @Resource
    SysUserApi sysUserApi;
    @Resource
    DevFileApi devFileApi;
    @Resource
    private DepotAlarmService depotAlarmService;
    @Resource
    private SysUserWxOpenSendLogService sysUserWxOpenSendLogService;
    @Resource
    CommonProperties commonProperties;
    @Resource
    CreateWxaQrCodeService createWxaQrCodeService;

    /**
     * 获取粮库表分页
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public Page<DepotGrain> page(DepotGrainPageParam depotGrainPageParam) {
        QueryWrapper<DepotGrain> queryWrapper = new QueryWrapper<>();
        List<String> orgIdLst = sysUserApi.ownOrgGrep(true);
        queryWrapper.lambda().in(CollUtil.isNotEmpty(orgIdLst), DepotGrain::getOrgId, orgIdLst);
        if (ObjectUtil.isNotEmpty(depotGrainPageParam.getDepotGrainName())) {
            queryWrapper.lambda().like(DepotGrain::getDepotGrainName, depotGrainPageParam.getDepotGrainName());
        }
        if (ObjectUtil.isAllNotEmpty(depotGrainPageParam.getSortField(), depotGrainPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(depotGrainPageParam.getSortOrder());
            queryWrapper.orderBy(true, depotGrainPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(depotGrainPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(DepotGrain::getId);
        }
        Page<DepotGrain> page = this.page(CommonPageRequest.defaultPage(), queryWrapper);
        //匹配完整图片地址
        putPicUrl(page.getRecords());
        return page;
    }

    /**
     * 获取业务权限粮库表列表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public List<String> lstOrgGrep() {
        return lstOrgGrep(true);
    }

    /**
     * 获取业务权限粮库表列表
     *
     * @param loginFlag true:登陆过滤
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public List<String> lstOrgGrep(boolean loginFlag) {
        List<String> lstOrgGrep = lstOrgGrep(new DepotGrainPageParam(loginFlag)).stream().map(DepotGrain::getDepotId).collect(Collectors.toList());
        return CollUtil.isEmpty(lstOrgGrep) ? Collections.singletonList("1") : lstOrgGrep;
    }

    /**
     * 获取业务权限粮库表列表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public List<DepotGrain> lstOrgGrep(DepotGrainPageParam param) {
        LambdaQueryWrapper<DepotGrain> wrapper = new LambdaQueryWrapper<>();
        List<String> orgIdLst = sysUserApi.ownOrgGrep(param.getLoginFlag());
        wrapper.in(CollUtil.isNotEmpty(orgIdLst), DepotGrain::getOrgId, orgIdLst);
        if (ObjectUtil.isNotEmpty(param.getDepotGrainName()))
            wrapper.like(DepotGrain::getDepotGrainName, param.getDepotGrainName());
        return this.list(wrapper);
    }

    /**
     * 获取粮库表列表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public List<DepotGrain> lst(DepotGrainPageParam param) {
        LambdaQueryWrapper<DepotGrain> wrapper = new LambdaQueryWrapper<>(BeanUtil.toBean(param, DepotGrain.class));
        wrapper.in(CollUtil.isNotEmpty(param.getDepotIdLst()), DepotGrain::getDepotId, param.getDepotIdLst());
        return this.list(wrapper);
    }

    /**
     * 获取粮库名称
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public String getNameByDepotId(String depotId) {
        if (Strings.isBlank(depotId)) return null;
        DepotGrain depotGrain = getOne(depotId);
        return depotGrain == null ? null : depotGrain.getDepotGrainName();
    }

    /**
     * 获取粮库
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public DepotGrain getOne(String depotId) {
        return getOne(new LambdaQueryWrapper<>(new DepotGrain(depotId)));
    }

    /**
     * 获取扦样区打开
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public boolean getOnSampling(String depotId) {
        DepotGrain getOne = getOne(depotId);
        return getOne != null && BizStr.STATE_ON.equals(getOne.getOnSampling());
    }

    /**
     * 添加粮库表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public void add(DepotGrainAddParam depotGrainAddParam) {
        repeatName(null, depotGrainAddParam.getDepotGrainName(), true);
        DepotGrain grain = BeanUtil.toBean(depotGrainAddParam, DepotGrain.class);
        grain.setDepotId(HexUtils.getByteTime14UUID5());
        //预约码
        grain.setQrCodePicUrl(devFileApi.storageFilePathReturnUrl(MultipartFileUtils.base64ToMultipart(createWxaQrCodeService.createWxaQrCode(grain.getDepotId(), grain.getDepotGrainName()))));
        this.save(grain);
    }

    /**
     * 编辑粮库表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public void edit(DepotGrainEditParam param) {
        repeatName(param.getId(), param.getDepotGrainName(), true);
        DepotGrain up = this.queryEntity(param.getId());
        //预约码
        if (!Objects.equals(param.getDepotGrainName(), up.getDepotGrainName()))
            up.setQrCodePicUrl(devFileApi.storageFilePathReturnUrl(MultipartFileUtils.base64ToMultipart(createWxaQrCodeService.createWxaQrCode(up.getDepotId(), param.getDepotGrainName()))));
        BeanUtil.copyProperties(param, up);
        this.updateById(up);
    }

    /**
     * 配置粮库表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public void set(DepotGrainEditParam depotGrainEditParam) {
        DepotGrain depotGrain = this.queryEntity(depotGrainEditParam.getId());
        BeanUtil.copyProperties(depotGrainEditParam, depotGrain);
        this.updateById(depotGrain);
    }

    /**
     * 删除粮库表
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<DepotGrainIdParam> depotGrainIdParamList) {
        // 执行删除
        this.removeBatchByIds(CollStreamUtil.toList(depotGrainIdParamList, DepotGrainIdParam::getId));
    }

    /**
     * 获取粮库表详情
     *
     * @author xiang
     * @date 2023/09/12 15:06
     */
    public DepotGrain detail(DepotGrainIdParam depotGrainIdParam) {
        /*DepotGrain grain = this.queryEntity(depotGrainIdParam.getId());
        Map<String, Object> map = new HashMap<>();
        map.put("depotGrainName", grain.getDepotGrainName());
        map.put("depotId", grain.getId());
        grain.setQrCodePicUrl(devFileApi.storageFilePathReturnUrl(MultipartFileUtils.base64ToMultipart(QRCodeUtil.createCodeToBase64(JSONUtil.toJsonStr(map)))));
        this.updateById(grain);*/
        return this.queryEntity(depotGrainIdParam.getId());
    }

    /**
     * 获取粮库表详情
     *
     * @author xiang
     * @date 2023/09/12 15:06
     **/
    public DepotGrain queryEntity(String id) {
        DepotGrain depotGrain = this.getById(id);
        if (depotGrain == null)
            depotGrain = getOne(id);
        if (ObjectUtil.isEmpty(depotGrain))
            throw new CommonException("粮库表不存在，id值为：{}", id);

        return depotGrain;
    }

    /**
     * 检查心跳
     *
     * @author xiang
     * @date 2023/09/12 15:06
     **/
    public void checkOnline(String dateTime) {
        LambdaQueryWrapper<DepotGrain> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DepotGrain::getOnlineState, BizStr.DEVICE_ON_LINE);
        wrapper.lt(DepotGrain::getOnlineTime, dateTime);
        List<DepotGrain> list = list(wrapper);
        if (list.isEmpty()) return;
        List<DepotAlarmAddParam> alarmAddParams = new ArrayList<>(list.size());
        list.forEach(one -> {
            DepotAlarmAddParam alarmAddParam = new DepotAlarmAddParam(
                    one.getDepotId(), BizStr.ALARM_PROJECT, String.format("上次在线时间：%s", one.getOnlineTime()));
            alarmAddParams.add(alarmAddParam);
            one.setOnlineState(BizStr.DEVICE_OFF_LINE);
            one.setUnionAlarmId(alarmAddParam.getId());
        });
        depotAlarmService.adds(alarmAddParams);
        updateBatchById(list);
        //推送微信公众号 项目离线
        sysUserWxOpenSendLogService.send(list, BizStr.ALARM_PROJECT);
    }

    /**
     * 心跳
     *
     * @author xiang
     * @date 2023/09/12 15:06
     **/
    public void putOnline(String depotId) {
        DepotGrain depotGrain = this.getOne(depotId);
        if (depotGrain == null) return;
        depotGrain.setOnlineTime(DatesUtil.forDateTime());
        //处理离线
        if (BizStr.DEVICE_OFF_LINE.equals(depotGrain.getOnlineState())) {
            depotAlarmService.processById(depotGrain.getUnionAlarmId());
            depotGrain.setOnlineState(BizStr.DEVICE_ON_LINE);
        }
        updateById(depotGrain);
    }

    /**
     * 匹配粮库名称
     *
     * @author xiang
     * @date 2023-01-01
     */
    public <T> void putDepotName(List<? extends BaseDepotGrainName> sources) {
        if (CollUtil.isEmpty(sources)) return;
        List<DepotGrain> lst = this.lst(new DepotGrainPageParam(null, sources.stream().map(BaseDepotGrainName::getDepotId).distinct().collect(Collectors.toList())));
        for (BaseDepotGrainName s : sources) {
            for (DepotGrain one : lst) {
                if (!Objects.equals(s.getDepotId(), one.getDepotId()))
                    continue;
                s.setDepotGrainName(one.getDepotGrainName());
                break;
            }
        }
    }

    /**
     * 检查名称重复
     *
     * @param throwFlag true:抛异常
     * @return true:重复
     * @author xiang
     * @date 2023-01-01
     */
    private boolean repeatName(String id, String name, boolean throwFlag) {
        List<DepotGrain> list = lst(new DepotGrainPageParam(null, name));
        if (list.isEmpty()) return false;
        if (Objects.equals(list.get(0).getId(), id) && list.size() == 1) return false;
        if (!throwFlag) return true;
        throw new CommonException(BizExceptionEnum.ERROR00005.getMessage());
    }

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

}
