package com.junmp.jyzb.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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 com.junmp.jyzb.api.bean.dto.InventorySumDto;
import com.junmp.jyzb.api.bean.dto.WarehouseDto;
import com.junmp.jyzb.api.bean.query.InAndOutRecordReq.CabinetLogsRecordReq;
import com.junmp.jyzb.api.bean.query.InventorySumReq;
import com.junmp.jyzb.api.bean.query.SelectTotalNumReq;
import com.junmp.jyzb.api.exception.enums.CabinetExceptionEnum;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.mapper.EquipmentCountSummaryMapper;
import com.junmp.jyzb.mapper.PriceSumSummaryMapper;
import com.junmp.jyzb.service.*;
import com.junmp.v2.common.exception.base.ServiceException;
import com.junmp.v2.common.util.BeanPlusUtil;
import com.junmp.v2.db.api.factory.PageFactory;
import com.junmp.v2.db.api.factory.PageResultFactory;
import com.junmp.v2.db.api.page.PageResult;
import com.junmp.v2.dict.entity.SysDictItem;
import com.junmp.v2.dict.service.SysDictItemService;
import org.springframework.stereotype.Service;
import com.junmp.jyzb.mapper.InventorySummaryMapper;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class InventorySummaryServiceImpl  extends ServiceImpl<InventorySummaryMapper, InventorySummary> implements InventorySummaryService {

    @Resource
    private PubOrgService pubOrgService;

    @Resource
    private OrderMainService orderMainService;

    @Resource
    private InventoryService inventoryService;

    @Resource
    private InventorySummaryMapper inventorySummaryMapper;

    @Resource
    private EquipmentSizeService equipmentSizeService;

    @Resource
    private OrderDetailService orderDetailService;

    @Resource
    private WarehouseService warehouseService;

    @Resource
    private LogSummaryService logSummaryService;

    @Resource
    private LogDetailService logDetailService;

    @Resource
    private CabinetBoxService cabinetBoxService;

    @Resource
    private SysDictItemService sysDictItemService;
    @Resource
    private PriceSumSummaryMapper PriceSumSummaryMapper;

    @Resource
    private EquipmentCountSummaryMapper equipmentCountSummaryMapper;

    @Resource
    private EquipmentTypeService equipmentTypeService;


    //根据条件查询库存汇总信息
    @Override
    public PageResult<InventorySummary> getEquipmentInfo(InventorySumReq req) {
        //当没有参数传递的时候默认查询全部，但是如果传递了条件，根据条件查询并且如果是根据id进行查询，则需要判断该id是否存在
        //判断组织机构是否存在
        if (ObjectUtil.isNotNull(req.getOrgId())){
            pubOrgService.PubOrgExist(Long.valueOf(req.getOrgId()));
        }
        //(如果传其他不是数据库字段参数或者排序规则不是deac或者asc可能会出现错误)
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) &&
                ObjectUtil.isNotNull(req.getOrder()) && !req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            req.setOrder(req.getOrder().toLowerCase());
        }
        LambdaQueryWrapper<InventorySummary> wp = createWrapper(req);//取出仓库中总数并计算
        Page<InventorySummary> page = page(PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize()), wp);
        List<InventorySummary> records = page.getRecords();
        LambdaQueryWrapper<EquipmentSize> sizeWrapper = new LambdaQueryWrapper<>();
        //将size表中的photo取出来，给前端显示
        Map<String,String> sizeMap=new HashMap<>();
        for (InventorySummary is:records) {
            String key=is.getTypeId()+"_"+is.getSizeId();
            if (!sizeMap.containsKey(key)){
                sizeMap.put(key,"1");
            }
        }
        // 使用 keySet 遍历
        //取出map中的所有进行遍历
        for (String key : sizeMap.keySet()) {
            String[] s = key.split("_");
            String typeId=s[0];
            String sizeId=s[1];
            sizeWrapper.or().eq(EquipmentSize::getTypeId,typeId).eq(EquipmentSize::getId,sizeId);
        }
        List<EquipmentSize> equipmentSizeList = equipmentSizeService.list(sizeWrapper);
        for (InventorySummary is:records) {
            for (EquipmentSize size:equipmentSizeList) {
                if (is.getSizeId().equals(size.getId())&& is.getTypeId().equals(size.getTypeId())){
                    is.setSizePhoto(size.getPhoto());
                    break;
                }
            }
        }
        //将type表中照片取出，给前端显示
        Map<String,String> typeMap=new HashMap<>();
        for (InventorySummary is:records) {
            String key=is.getTypeId();
            if (!sizeMap.containsKey(key)){
                sizeMap.put(key,"1");
            }
        }
        LambdaQueryWrapper<EquipmentType> typeWrapper = new LambdaQueryWrapper<>();
        for (String key : sizeMap.keySet()) {
            typeWrapper.or().eq(EquipmentType::getId,key);
        }
        List<EquipmentType> equipmentTypeList = equipmentTypeService.list(typeWrapper);
        for (InventorySummary is:records ) {
            for (EquipmentType type:equipmentTypeList) {
                if (is.getTypeId().equals(type.getId())){
                    is.setTypePhoto(type.getPhoto());
                    break;
                }
            }
        }
        page.setRecords(records);
        return PageResultFactory.createPageResult(page);
    }

    @Override
    public PageResult<InventorySummary> GetEquipmentSummary(InventorySumReq req) {
        //(如果传其他不是数据库字段参数或者排序规则不是deac或者asc可能会出现错误)
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) &&
                ObjectUtil.isNotNull(req.getOrder()) && !req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            req.setOrder(req.getOrder().toLowerCase());
        }
        int size=inventorySummaryMapper.GetEquipmentSummarySum(req);
        List<InventorySummary> list=inventorySummaryMapper.GetEquipmentSummary(req,(req.getPageNo()-1)*req.getPageSize(),req.getPageSize());
        Page<InventorySummary> page = PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize());
        page.setRecords(list);
        page.setTotal(size);
        return  PageResultFactory.createPageResult(page);
    }

    @Override
    public List<InventorySummary> GetEquipmentSummaryDetail(InventorySumReq req) {
        //(如果传其他不是数据库字段参数或者排序规则不是deac或者asc可能会出现错误)
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) &&
                ObjectUtil.isNotNull(req.getOrder()) && !req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            req.setOrder(req.getOrder().toLowerCase());
        }
        return inventorySummaryMapper.GetEquipmentSummaryDetail(req);
    }

    @Override
    public List<InventorySummary> getEquipmentInfoList(InventorySumReq req) {
        //当没有参数传递的时候默认查询全部，但是如果传递了条件，根据条件查询并且如果是根据id进行查询，则需要判断该id是否存在
        //(如果传其他不是数据库字段参数或者排序规则不是deac或者asc可能会出现错误)
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) &&
                ObjectUtil.isNotNull(req.getOrder()) && !req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            req.setOrder(req.getOrder().toLowerCase());
        }
        LambdaQueryWrapper<InventorySummary> wp = createWrapper(req);//取出仓库中总数并计算
        return list(wp);

    }

    /**
     * 用于出库单中的装备选择
     * @return
     */
    @Override
    public List<InventorySumDto> GetInventorySumInfo(InventorySumReq req) {

        return inventorySummaryMapper.GetInventorySumInfo(req);
    }

    @Override
    public InventorySummary getOne(InventorySumReq req) {
        LambdaQueryWrapper<InventorySummary> eq = new LambdaQueryWrapper<InventorySummary>()
                .eq(ObjectUtil.isNotEmpty(req.getOrgId()), InventorySummary::getOrgId, req.getOrgId())
                .eq(ObjectUtil.isNotEmpty(req.getLocationId()), InventorySummary::getLocationId, req.getLocationId())
                .eq(ObjectUtil.isNotEmpty(req.getTypeId()), InventorySummary::getTypeId, req.getTypeId())
                .eq(ObjectUtil.isNotEmpty(req.getSizeId()), InventorySummary::getSizeId, req.getSizeId())
                .eq(ObjectUtil.isNotEmpty(req.getUnitPrice()), InventorySummary::getUnitPrice, req.getUnitPrice());
        InventorySummary one = getOne(eq);
        return one;
    }


    //对summary表中数据进行重新计算装备信息汇总
    public Boolean updateSummaryInsByOrder(Long orgId){
        //查询字典表中的临近报废天数
        SysDictItem sysDictItem = sysDictItemService.getOne(new LambdaQueryWrapper<SysDictItem>()
                .eq(SysDictItem::getItemText, "brokenNumber"));
        //如果配置找不到，那就默认设置为15天为临近报废（如果装备的质保期小于15天了，就是为临近报废）
        Integer brokenNumberDays;
        if (ObjectUtil.isNotNull(sysDictItem)){
            brokenNumberDays=15;
        }else {
            brokenNumberDays=Integer.parseInt(sysDictItem.getItemValue());
        }
        //查询出组织机构下的所有仓库信息，并且将表中的仓库信息数据进行删除
        List<WarehouseDto> allWarehouse = warehouseService.getAllWarehouse(orgId,-1);
        boolean a = inventorySummaryMapper.deleteByWarehouse(allWarehouse);
        //根据仓库id重新计算汇总信息
        boolean sumByWarehouse = inventorySummaryMapper.getSumByWarehouse(allWarehouse, brokenNumberDays);
        return (a && sumByWarehouse);
    }

    //单警柜返回数据
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cabinetInOutRecords(CabinetLogsRecordReq req) {
        //批量修改装备信息
//        List<InventoryReq> inventoryList = req.getInventoryList();
        boolean a=true;
//        List<Inventory> inventoryLogsList=new ArrayList<>();
//        for (InventoryReq inventoryReq:inventoryList) {
//            Inventory inventory = new Inventory();
//            BeanPlusUtil.copyProperties(inventoryReq,inventory);
//            boolean result = inventoryService.saveOrUpdate(inventory);
//            inventoryLogsList.add(inventory);
//            if (!result){
//                a=false;
//                break;
//            }
//        }
        //修改summary表中数据
//        boolean b = updateSummaryInsByCabinet(req.getLocationId());
        //添加日志记录、
//        Boolean c = insertCabinetLog(req,inventoryLogsList);
        return (a  );
    }


    public boolean updateSummaryInsByCabinet(String locationId){
        //查询字典表中的临近报废天数
        SysDictItem sysDictItem = sysDictItemService.getOne(new LambdaQueryWrapper<SysDictItem>()
                .eq(SysDictItem::getItemText, "brokenNumber"));
        //如果配置找不到，那就默认设置为15天为临近报废（如果装备的质保期小于15天了，就是为临近报废）
        Integer brokenNumberDays;
        if (ObjectUtil.isNotNull(sysDictItem)){
            brokenNumberDays=15;
        }else {
            brokenNumberDays=Integer.parseInt(sysDictItem.getItemValue());
        }
        //根据箱门id查询出单警柜信息
        CabinetBox cabinetBox = cabinetBoxService.getById(locationId);
        //删除inventorysummary表中该单警柜数据
        boolean a = inventorySummaryMapper.deleteByCabinet(cabinetBox.getCabinetId());
        //重新计算该单警柜下面的装备信息
        boolean b = inventorySummaryMapper.getSumByCabinet(cabinetBox.getCabinetId(),brokenNumberDays);
        return (a && b);
    }

    //添加单警柜出入库记录日志
    public Boolean insertCabinetLog(CabinetLogsRecordReq req,List<Inventory> inventoryLogsList){

        LogSummary logSummary = new LogSummary();
        BeanPlusUtil.copyProperties(req,logSummary);
        logSummary.setLocationType(1);
        boolean a = logSummaryService.save(logSummary);
        List<LogDetail> logDetailList=new ArrayList<>();
        for (Inventory inventory:inventoryLogsList) {
            LogDetail logDetail = new LogDetail();
            BeanPlusUtil.copyProperties(inventory,logDetail);
            logDetail.setInventoryId(inventory.getId());
//            logDetail.setCabinetboxId(req.getLocationId());
            logDetail.setOutInState(inventory.getLocationState());
            logDetail.setSummaryId(logSummary.getId());
            logDetailList.add(logDetail);
        }
        boolean b = logDetailService.saveBatch(logDetailList);
        return (a && b);
    }

    //根据组织机构id/单警柜id/仓库id查询出库存汇总数量以及金额
    @Override
    public List<InventorySummary> getTotalNumberAndPrice(InventorySumReq req) {
        List<InventorySummary> list=new ArrayList<>();
        InventorySummary totalNumberAndPrice = inventorySummaryMapper.getTotalNumberAndPrice(req);
        if (ObjectUtil.isNotNull(totalNumberAndPrice)){
            list.add(totalNumberAndPrice);
        }

        return list;
    }


    //计算装备总数（装备数量数据统计）
    @Override
    public List<InventorySummary> EquipmentStatistics(InventorySumReq req) {
        List<InventorySummary> inventorySummaryList=new ArrayList<>();
        InventorySummary inventorySummary = inventorySummaryMapper.EquipmentStatistics(req);
        if (ObjectUtil.isNotNull(inventorySummary)){
            inventorySummaryList.add(inventorySummary);
        }
        return inventorySummaryList;
    }


    //根据条件查询库存汇总
    @Override
    public List<InventorySummary> selectSumByItems(SelectTotalNumReq req) {
        List<InventorySumReq> list = req.getList();
        List<Object[]> searchItem=new ArrayList<>();
        for (InventorySumReq inv:list) {
            Object[] item=new Object[]{inv.getOrgId(),inv.getLocationId(),inv.getTypeId(),inv.getSizeId(),inv.getUnitPrice()};
            searchItem.add(item);
        }
        List<InventorySummary> inventorySummaryList = inventorySummaryMapper.selectSumByItems(searchItem);
        //判断装备的list是否和传入的list的size是否相等，如果相等则表示所有的库存数量都能查询到，如果不相等则进行遍历将不满足要求的进行新增一条装备数量为0的库存信息进行返回给前端
        if (list.size()==inventorySummaryList.size()){
            return inventorySummaryList;
        }else {
            List<InventorySummary> returnList=new ArrayList<>();
            for (InventorySumReq inv:list) {
                boolean flag=false;
                for (InventorySummary is:inventorySummaryList) {
                    if (inv.getOrgId().equals(is.getOrgId())&& inv.getLocationId().equals(is.getLocationId())
                            && inv.getTypeId().equals(is.getTypeId()) && inv.getSizeId().equals(is.getTypeId())
                            && is.getUnitPrice().compareTo(new BigDecimal(inv.getUnitPrice()))==0){
                        flag=true;
                        returnList.add(is);
                        break;
                    }
                }
                if (!flag){
                    InventorySummary inventorySummary = new InventorySummary();
                    BeanPlusUtil.copyProperties(inv,inventorySummary);
                    inventorySummary.setStockNumber(0);
                    inventorySummary.setOutboundNumber(0);
                    inventorySummary.setPrice(BigDecimal.ZERO);
                    inventorySummary.setBrokenNumber(0);
                    inventorySummary.setDestructionNumber(0);
                    returnList.add(inventorySummary);
                }

            }
            return returnList;
        }

    }

    @Override
    public boolean insertToSummary() {
        String summaryTableName="base_inventory_summary_type2";
        String sourceTableName="base_inventory_copy1";
        //临近报废设置配置值
        //应该要去数据库进行查询，但是现在目前写死15天
        Integer warrantyThreshold=15;
        inventorySummaryMapper.insertToSummary(summaryTableName,sourceTableName,warrantyThreshold);
        return true;
    }

    @Override
    public List<InventorySumDto> selectTotalNum(SelectTotalNumReq req) {
        List<Object[]> searchCriteria=new ArrayList<>();
        if (req.getList().isEmpty()){
            throw new ServiceException(CabinetExceptionEnum.PARAMETER_ERROR) ;
        }
        for (InventorySumReq inventorySumReq:req.getList()) {
            Object[] criteria=new Object[]{inventorySumReq.getTypeId(),inventorySumReq.getSizeId()};
            searchCriteria.add(criteria);
        }
        List<InventorySumDto> inventorySumDtoList=inventorySummaryMapper.selectTotalNum(req.getOrgId(),searchCriteria);
        return inventorySumDtoList;
    }



    private LambdaQueryWrapper<InventorySummary> createWrapper(InventorySumReq req) {
        LambdaQueryWrapper<InventorySummary> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isEmpty(req)) {
            return wrapper;
        }
        /**
         * 判断是否有高级搜索，如果有则进行添加查询条件
         */
        if (ObjectUtil.isNotNull(req.getNumber())){
            //将值进行切割，> = <并将其判断为哪个符号，如果为>则使用ge，=为eq，<为le
            String symbol = req.getNumber().substring(0, 1);
            String value = req.getNumber().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getNumber,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getNumber,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getNumber,value);
            }
        }
        if (ObjectUtil.isNotNull(req.getStockNumber())){
            String symbol = req.getStockNumber().substring(0, 1);
            String value = req.getStockNumber().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getStockNumber,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getStockNumber,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getStockNumber,value);
            }
        }
        if (ObjectUtil.isNotNull(req.getOutboundNumber())){
            String symbol = req.getOutboundNumber().substring(0, 1);
            String value = req.getOutboundNumber().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getOutboundNumber,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getOutboundNumber,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getOutboundNumber,value);
            }
        }
        if (ObjectUtil.isNotNull(req.getExpireNumber())){
            String symbol = req.getExpireNumber().substring(0, 1);
            String value = req.getExpireNumber().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getExpireNumber,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getExpireNumber,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getExpireNumber,value);
            }
        }
        if (ObjectUtil.isNotNull(req.getBrokenNumber())){
            String symbol = req.getBrokenNumber().substring(0, 1);
            String value = req.getBrokenNumber().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getBrokenNumber,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getBrokenNumber,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getBrokenNumber,value);
            }
        }
        if (ObjectUtil.isNotNull(req.getUnitPrice())){
            String symbol = req.getUnitPrice().substring(0, 1);
            String value = req.getUnitPrice().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getUnitPrice,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getUnitPrice,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getUnitPrice,value);
            }
        }
        if (ObjectUtil.isNotNull(req.getPrice())){
            String symbol = req.getPrice().substring(0, 1);
            String value = req.getPrice().substring(1);
            if (symbol.equals(">")){
                wrapper.gt(InventorySummary::getPrice,value);
            } else if (symbol.equals("=")) {
                wrapper.eq(InventorySummary::getPrice,value);
            }else if (symbol.equals("<")){
                wrapper.lt(InventorySummary::getPrice,value);
            }
        }
        //根据组织机构号查询
        wrapper.eq(ObjectUtil.isNotEmpty(req.getOrgId()), InventorySummary::getOrgId, req.getOrgId());
        //根据组织机构名模糊查询
        wrapper.like(ObjectUtil.isNotEmpty(req.getOrgName()), InventorySummary::getOrgName, req.getOrgName());
        //位置id（单警柜/仓库）
        wrapper.eq(ObjectUtil.isNotEmpty(req.getLocationId()), InventorySummary::getLocationId, req.getLocationId());
        //位置类型
        wrapper.eq(ObjectUtil.isNotNull(req.getLocationType())&& !req.getLocationType().trim().isEmpty(),InventorySummary::getLocationType,req.getLocationType());
        //位置信息
        wrapper.like(ObjectUtil.isNotEmpty(req.getLocationName()), InventorySummary::getLocationName, req.getLocationName());
        //根据类别
        if (ObjectUtil.isNotEmpty(req.typeIds) && req.typeIds.size()>0) {
            wrapper.and(qw -> req.typeIds.forEach(typeId -> qw.or().eq(InventorySummary::getTypeId, typeId)));
        }
        //根据类别
        if (ObjectUtil.isNotEmpty(req.sizeIds) && req.sizeIds.size()>0) {
            wrapper.and(qw -> req.sizeIds.forEach(sizeId -> qw.or().eq(InventorySummary::getSizeId, sizeId)));
        }
        //根据类别
        if (ObjectUtil.isNotEmpty(req.getSizeNames()) && req.getSizeNames().size()>0) {
            wrapper.and(qw -> req.getSizeNames().forEach(sizeName -> qw.or().eq(InventorySummary::getSizeName, sizeName)));
        }
        if (ObjectUtil.isNotEmpty(req.getColumn())&&!req.getColumn().equals("create_time"))
        {
            wrapper.last("order by " + req.getColumn() + " " + req.getOrder());
        }
        else
        {
            wrapper.last("order by type_id");
        }


        return wrapper;
    }
}
