package com.kxs.store.biz.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kxs.common.core.constant.SecurityConstants;
import com.kxs.common.core.constant.enums.ErrorTypeEnum;
import com.kxs.common.core.constant.enums.MachineTypeEnum;
import com.kxs.common.core.exception.GlobalCustomerException;
import com.kxs.common.core.util.R;
import com.kxs.common.core.util.RetOps;
import com.kxs.common.security.util.SecurityUtils;
import com.kxs.product.api.feign.RemoteKxsProductService;
import com.kxs.product.api.model.KxsBrand;
import com.kxs.product.api.model.KxsMachine;
import com.kxs.store.api.dto.kxsapp.storeRecycle.RecycleConfirmDTO;
import com.kxs.store.api.dto.kxsapp.storeRecycle.RecycleSubmitDTO;
import com.kxs.store.api.dto.kxsapp.storeRecycle.StoreRecycleMachineListDTO;
import com.kxs.store.api.dto.kxsapp.storeRecycle.UserReturnRecycleDTO;
import com.kxs.store.api.model.KxsMachineRecycleInfo;
import com.kxs.store.api.model.KxsWarehouse;
import com.kxs.store.api.vo.kxsapp.storeRecycle.*;
import com.kxs.store.biz.constant.enums.RecycleOrderEnum;
import com.kxs.store.biz.constant.enums.StoreErrorTypeEnum;
import com.kxs.store.biz.mapper.KxsMachineRecycleInfoMapper;
import com.kxs.store.biz.mapper.KxsMachineRecycleMapper;
import com.kxs.store.api.model.KxsMachineRecycle;
import com.kxs.store.biz.mapper.KxsWarehouseMapper;
import com.kxs.store.biz.service.KxsMachineRecycleService;
import com.kxs.system.api.feign.RemoteUserMsgService;
import com.kxs.system.api.model.KxsUserMsg;
import com.kxs.system.api.util.MsgTemplateUtil;
import com.kxs.user.api.feign.RemoteKxsUserService;
import com.kxs.user.api.model.KxsUser;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 客小爽仓库机具回收申请表(KxsMachineRecycle)表服务实现类
 *
 * @author 系统
 * @since 2024-01-08 09:46:02
 */
@Service("kxsMachineRecycleService")
@RequiredArgsConstructor
public class KxsMachineRecycleServiceImpl extends ServiceImpl<KxsMachineRecycleMapper, KxsMachineRecycle> implements KxsMachineRecycleService {

    private final KxsMachineRecycleInfoMapper kxsMachineRecycleInfoMapper;

    private final RemoteKxsProductService remoteKxsProductService;

    private final RemoteUserMsgService remoteUserMsgService;

    private final RemoteKxsUserService remoteKxsUserService;

    private final KxsWarehouseMapper kxsWarehouseMapper;

    @Override
    public IPage<StoreRecycleMachineListVO> getByPage(Page<StoreRecycleMachineListVO> page, StoreRecycleMachineListDTO param) {

        param.setWarehouseUserId(SecurityUtils.getUser().getId());

        //自定义分页
        long start = (page.getCurrent() - 1) * page.getSize();
        start = start < 0 ? 0L : start;

        List<StoreRecycleMachineListVO> orderListVos = baseMapper.getByPage(start, page.getSize(), param);
        orderListVos.parallelStream().forEach(item -> item.setTotalNumber(item.getSnList().size()));
        page.setRecords(orderListVos);

        return page;
    }

    @Override
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public R confirm(RecycleConfirmDTO param) {

        KxsMachineRecycle machineRecycle = baseMapper.selectById(param.getId());
        if(machineRecycle == null){
            return R.failed(StoreErrorTypeEnum.DATA_ERROR.getDescription());
        }
        List<KxsMachineRecycleInfo> recycleInfos = kxsMachineRecycleInfoMapper.selectList(Wrappers.<KxsMachineRecycleInfo>lambdaQuery()
                .eq(KxsMachineRecycleInfo::getStatus, RecycleOrderEnum.INFO_UNCONFIRM.getType())
                .eq(KxsMachineRecycleInfo::getOrderId, machineRecycle.getId()));
        if(recycleInfos.isEmpty()){
            return R.failed(StoreErrorTypeEnum.DATA_ERROR.getDescription());
        }
        for (KxsMachineRecycleInfo recycleInfo : recycleInfos) {
            if(param.getSnList().contains(recycleInfo.getPosSn())){
                //远程查询机具号
                R<KxsMachine> kxsMachineR = remoteKxsProductService.loadMachineBySn(recycleInfo.getPosSn(), SecurityConstants.FROM_IN);
                KxsMachine machine = RetOps.of(kxsMachineR)
                        .getData()
                        .orElseThrow(() -> new GlobalCustomerException(StoreErrorTypeEnum.SN_FIND_NULL.getDescription()));
                if(Objects.equals(machine.getBindStatus(), MachineTypeEnum.BIND.getType())){
                    throw new GlobalCustomerException("机具" + machine.getPosSn() + "已被绑定，请驳回该机具");
                }

                recycleInfo.setStatus(RecycleOrderEnum.INFO_CONFIRM.getType());
                recycleInfo.setConfirmTime(LocalDateTime.now());
                kxsMachineRecycleInfoMapper.updateById(recycleInfo);
                //修改机具
                machine.setWarehouseId(machineRecycle.getWarehouseId());
                machine.setUserId(0);
//                machine.setStatus(MachineTypeEnum.RECYCLE_CONFIRM.getType());
                machine.setMachineType(MachineTypeEnum.M_TYPE_SN.getType());
                R<Boolean> booleanR = remoteKxsProductService.updateByMachine(machine, SecurityConstants.FROM_IN);
                if(!booleanR.getData()){
                    throw new GlobalCustomerException(ErrorTypeEnum.REMOTE_DATA_ERROR.getDescription());
                }
            }
        }

        return R.ok();
    }


    @Override
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public R cancel(RecycleConfirmDTO param) {

        KxsMachineRecycle recycleOrder = baseMapper.selectById(param.getId());

        if(recycleOrder == null){
            return R.failed(StoreErrorTypeEnum.DATA_ERROR.getDescription());
        }
        List<KxsMachineRecycleInfo> recycleInfos = kxsMachineRecycleInfoMapper.selectList(Wrappers.<KxsMachineRecycleInfo>lambdaQuery()
                .eq(KxsMachineRecycleInfo::getStatus, RecycleOrderEnum.INFO_UNCONFIRM.getType())
                .eq(KxsMachineRecycleInfo::getOrderId, recycleOrder.getId()));

        for (KxsMachineRecycleInfo recycleInfo : recycleInfos) {
            if(param.getSnList().contains(recycleInfo.getPosSn())){
                recycleInfo.setStatus(RecycleOrderEnum.INFO_CANCEL.getType());
                recycleInfo.setCancelTime(LocalDateTime.now());
                kxsMachineRecycleInfoMapper.updateById(recycleInfo);

                //修改机具状态未可回收
                R<KxsMachine> kxsMachineR = remoteKxsProductService.loadMachineBySn(recycleInfo.getPosSn(), SecurityConstants.FROM_IN);
                KxsMachine machine = RetOps.of(kxsMachineR)
                        .getData()
                        .orElseThrow(() -> new GlobalCustomerException(StoreErrorTypeEnum.SN_FIND_NULL.getDescription()));
                machine.setStatus(MachineTypeEnum.RECYCLE_STATUS.getType());

                R<Boolean> booleanR = remoteKxsProductService.updateByMachine(machine, SecurityConstants.FROM_IN);
                if(!booleanR.getData()){
                    throw new GlobalCustomerException(ErrorTypeEnum.REMOTE_DATA_ERROR.getDescription());
                }
            }
        }

        return R.ok();
    }


    @Override
    public StoreRecycleDataVO recycleCount() {

        Long userId = SecurityUtils.getUser().getId();

        StoreRecycleDataVO storeRecycleDataVO = new StoreRecycleDataVO();

        //待确认机具数量
        Integer recycleCount = baseMapper.storeRecoverableData(userId.intValue(), 0);
        storeRecycleDataVO.setRecycleCount(recycleCount);
        //已完成
        Integer recyclableCount = baseMapper.storeRecoverableData(userId.intValue(), 1);
        storeRecycleDataVO.setRecyclableCount(recyclableCount);

        return storeRecycleDataVO;
    }

    @Override
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public R userSubmit(RecycleSubmitDTO param) {

        KxsMachineRecycle machineRecycle = new KxsMachineRecycle();
        Long userId = SecurityUtils.getUser().getId();
        //查询用户
        R<KxsUser> kxsUserR = remoteKxsUserService.loadUserById(userId.intValue(), SecurityConstants.FROM_IN);
        KxsUser user = RetOps.of(kxsUserR)
                .getData()
                .orElseThrow(() -> new GlobalCustomerException(ErrorTypeEnum.USER_NOT_FOUND.getDescription()));
        //查询品牌
        R<KxsBrand> kxsBrandR = remoteKxsProductService.loadByBrand(param.getBrandId(), SecurityConstants.FROM_IN);
        KxsBrand brand = RetOps.of(kxsBrandR)
                .getData()
                .orElseThrow(() -> new GlobalCustomerException(StoreErrorTypeEnum.DATA_ERROR.getDescription()));
        //查询仓库
        KxsWarehouse kxsWarehouse = kxsWarehouseMapper.selectById(param.getWarehouseId());
        if(kxsWarehouse == null){
            return R.failed(StoreErrorTypeEnum.STORE_NOT_FIND.getDescription());
        }
        BeanUtils.copyProperties(param, machineRecycle);
        //订单号
        Snowflake snowflake = IdUtil.getSnowflake(1, userId);
        long orderSn = snowflake.nextId();
        machineRecycle.setOrderSn("JJHS" + orderSn);

        machineRecycle.setUserId(userId.intValue());
        machineRecycle.setUsername(user.getUsername());
        machineRecycle.setUserCode(user.getUserCode());
        machineRecycle.setPhone(user.getPhone());
        machineRecycle.setWarehouseUserId(kxsWarehouse.getUserId());
        machineRecycle.setBrandName(brand.getName());
        //添加数据
        baseMapper.insert(machineRecycle);
        //添加机具号数据
        for (String sn : param.getSnList()) {
            R<KxsMachine> kxsMachineR = remoteKxsProductService.loadMachineBySn(sn, SecurityConstants.FROM_IN);
            KxsMachine machine = RetOps.of(kxsMachineR)
                    .getData()
                    .orElseThrow(() -> new GlobalCustomerException(StoreErrorTypeEnum.DATA_ERROR.getDescription()));
            if(!Objects.equals(machine.getStatus(), MachineTypeEnum.RECYCLE_STATUS.getType())){
                throw new GlobalCustomerException("机具号" + machine.getPosSn() + "不可回收");
            }

            KxsMachineRecycleInfo kxsMachineRecycleInfo = new KxsMachineRecycleInfo();
            kxsMachineRecycleInfo.setPosSn(sn);
            kxsMachineRecycleInfo.setOrderId(machineRecycle.getId());
            kxsMachineRecycleInfo.setBrandId(brand.getId());
            kxsMachineRecycleInfo.setRecycleEndTime(machine.getRecycleEndTime());
            kxsMachineRecycleInfoMapper.insert(kxsMachineRecycleInfo);

//            machine.setStatus(MachineTypeEnum.RECYCLE_UN_CONFIRM.getType());
//            R<Boolean> booleanR = remoteKxsProductService.updateByMachine(machine, SecurityConstants.FROM_IN);
//            if (!booleanR.getData()) {
//                throw new GlobalCustomerException(ErrorTypeEnum.REMOTE_DATA_ERROR.getDescription());
//            }
        }
        KxsUserMsg kxsUserMsg = MsgTemplateUtil.machineRecycleNote(param.getSnList(), brand.getName(), kxsWarehouse.getUserId(), user.getUserCode());
        remoteUserMsgService.pushUserMsg(kxsUserMsg, SecurityConstants.FROM_IN);

        return R.ok();
    }

    @Override
    public IPage<RecycleUserListVO> userList(Page<RecycleUserListVO> page) {

        Long userId = SecurityUtils.getUser().getId();
        //自定义分页
        long start = (page.getCurrent() - 1) * page.getSize();
        start = start < 0 ? 0L : start;

        Long count = baseMapper.selectCount(Wrappers.<KxsMachineRecycle>lambdaQuery()
                .eq(KxsMachineRecycle::getUserId, userId));
        page.setTotal(count);

        List<RecycleUserListVO> byPage = baseMapper.userList(start, page.getSize(), userId);
        page.setRecords(byPage);

        return page;
    }

    @Override
    public IPage<NeedConfirmRecycleVO> needConfirmList(Page<NeedConfirmRecycleVO> page, Integer brandId) {

        Long userId = SecurityUtils.getUser().getId();

        return baseMapper.needConfirmList(page, userId, brandId);

    }

    @Override
    public recoverableDataVO recoverableData() {

        Long userId = SecurityUtils.getUser().getId();

        recoverableDataVO recoverableDataVO = new recoverableDataVO();
        //待确认数量
        Integer count = baseMapper.recoverableData(userId);

        R<Integer> integerR = remoteKxsProductService.loadRecoverableData(userId, SecurityConstants.FROM_IN);
        Integer recoverableCount = RetOps.of(integerR)
                .getData()
                .orElse(0);

        recoverableDataVO.setNeedConfirmCount(count);
        recoverableDataVO.setRecoverableCount(recoverableCount);
        return recoverableDataVO;
    }

    @Override
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public R userReturnRecycle(UserReturnRecycleDTO userReturnRecycleDTO) {

        userReturnRecycleDTO.getSnList().parallelStream().forEach(sn -> {
            KxsMachineRecycleInfo recycleInfo = kxsMachineRecycleInfoMapper.selectOne(Wrappers.lambdaQuery(KxsMachineRecycleInfo.class)
                    .eq(KxsMachineRecycleInfo::getStatus, RecycleOrderEnum.INFO_UNCONFIRM.getType())
                    .eq(KxsMachineRecycleInfo::getPosSn, sn));
            if (recycleInfo == null) {
                throw new GlobalCustomerException(sn + "机具已处理");
            }
            //删除回收机具
            kxsMachineRecycleInfoMapper.deleteById(recycleInfo.getId());
            //修改机具状态未可回收
//            R<KxsMachine> kxsMachineR = remoteKxsProductService.loadMachineBySn(sn, SecurityConstants.FROM_IN);
//            KxsMachine machine = RetOps.of(kxsMachineR)
//                    .getData()
//                    .orElseThrow(() -> new GlobalCustomerException(StoreErrorTypeEnum.SN_FIND_NULL.getDescription()));
//            machine.setStatus(MachineTypeEnum.RECYCLE_CANCEL.getType());
//
//            R<Boolean> booleanR = remoteKxsProductService.updateByMachine(machine, SecurityConstants.FROM_IN);
//            if(!booleanR.getData()){
//                throw new GlobalCustomerException(ErrorTypeEnum.REMOTE_DATA_ERROR.getDescription());
//            }

            //删除主订单
            Long count = kxsMachineRecycleInfoMapper.selectCount(Wrappers.lambdaQuery(KxsMachineRecycleInfo.class)
                    .eq(KxsMachineRecycleInfo::getOrderId, recycleInfo.getOrderId()));
            if(count == 0){
                baseMapper.deleteById(recycleInfo.getOrderId());
            }
        });

        return R.ok();
    }

    @Override
    public List<String> recycleSnList() {
        Long userId = SecurityUtils.getUser().getId();

        return baseMapper.recycleUserSnList(userId);
    }


}

