package com.bs.jxc.controller;

import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bs.common.annotation.Log;
import com.bs.common.core.controller.BaseController;
import com.bs.common.core.domain.AjaxResult;
import com.bs.common.core.page.TableDataInfo;
import com.bs.common.enums.BusinessType;
import com.bs.common.utils.poi.ExcelUtil;
import com.bs.jxc.domain.*;
import com.bs.jxc.service.*;
import com.bs.system.service.ISysConfigService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 仓库库存Controller
 *
 * @author bs
 * @date 2023-07-10
 */
@Api(tags = "仓库库存")
@RestController
@RequestMapping("/jxc/ckstock")
public class CkCargoStockController extends BaseController {
    @Resource
    private ICkCargoStockService ckCargoStockService;
    @Resource
    private ICmWarehouseService cmWarehouseService;
    @Resource
    private ICmStockService cmStockService;
    @Resource
    private ISysConfigService configService;
    @Resource
    private ICkBillCargoService ckBillCargoService;
    @Resource
    private ICkBillService ckBillService;
    /**
     * 分页查询仓库库存列表
     */
    @ApiOperation("分页查询仓库库存列表")
    @GetMapping("/pageList")
    public TableDataInfo pageList(CkCargoStock ckCargoStock) {
        startPage();
        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();
        condition(queryWrapper, ckCargoStock);
        if (ckCargoStock.getIsShow()) {
            queryWrapper.gt(CkCargoStock::getCargoWt, 0);
        }
        if (null != ckCargoStock.getBeginDateOut()) {
            queryWrapper.gt(CkCargoStock::getStockDate, ckCargoStock.getBeginDateOut());
        }
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);

        List<CkCargoStock> ckCargoStocks = outRecovery(list, ckCargoStock);
        return getDataTable(ckCargoStocks);
    }

    public List<CkCargoStock> outRecovery(List<CkCargoStock> list,CkCargoStock ckCargoStock) {
        if (null != ckCargoStock.getEndDateOut()) {
            for (CkCargoStock ckCargoStockVo : list) {
                LambdaQueryWrapper<CkBill> queryWrapperBill = new LambdaQueryWrapper();
                queryWrapperBill.ne(CkBill::getBillType, "1");
                queryWrapperBill.inSql(CkBill::getId, "select a.bill_id from ck_bill_cargo a, ck_bill_stock b where a.id = b.bill_cargo_id and b.bill_number like '%"+
                        ckCargoStockVo.getBillNumber() +"%'")
                            .eq(CkBill::getBillStatus,"1");
                List<CkBill> listBill = ckBillService.list(queryWrapperBill);
                BigDecimal totalCargoWt = BigDecimal.ZERO;
                BigDecimal totalCargoValue = BigDecimal.ZERO;
                for (CkBill ckBill : listBill) {
                    MPJLambdaWrapper<CkBillCargo> queryWrapperBillCargo = new MPJLambdaWrapper();
                    queryWrapperBillCargo.eq(CkBillCargo::getInoutType, "2")
                            .eq(CkBillCargo::getBillNumber, ckBill.getBillNumber())
                            .gt(CkBillCargo::getBillDate, ckCargoStock.getEndDateOut());
                    if ("4".equals(ckBill.getBillType())) {
                        queryWrapperBillCargo.eq(CkBillCargo::getListNumber,ckCargoStockVo.getListNumber());
                    }
                    List<CkBillCargo> listBillCargo = ckBillCargoService.list(queryWrapperBillCargo);
                    for (CkBillCargo ckBillCargo : listBillCargo) {
                        System.out.println( ckBillCargo.getBillNumber() + "+++"  + ckBillCargo.getCargoWt());
                        totalCargoWt = totalCargoWt.add(ckBillCargo.getCargoWt());
                        totalCargoValue = totalCargoValue.add(ckBillCargo.getCargoValue());
                    }
                }
                ckCargoStockVo.setCargoWt(ckCargoStockVo.getCargoWt().add(totalCargoWt));
                ckCargoStockVo.setCargoValue(ckCargoStockVo.getCargoValue().add(totalCargoValue));
            }
        }
        return list;
    }

    /**
     * 分页查询即将过期仓库库存列表
     */
    @ApiOperation("分页查询仓库库存列表")
    @GetMapping("/pageListByExpire")
    public TableDataInfo pageListByExpire(CkCargoStock ckCargoStock) {
        String expirationDate = configService.selectConfigByKey("inBillCargoExpiryDateWarn");
        if (expirationDate == null || expirationDate.isEmpty()) {
            expirationDate = "45";
        }
        startPage();
        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();

        LocalDate today = LocalDate.now();
        LocalDate yesterday = today.minusDays(1);
        LocalDate expirationLimit = today.plusDays(Long.parseLong(expirationDate));
        queryWrapper.le(CkCargoStock::getExpiryDate, expirationLimit)
                    .gt(CkCargoStock::getExpiryDate, yesterday);
        condition(queryWrapper, ckCargoStock);
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);
        return getDataTable(list);
    }

    /**
     * 查询仓库库存列表
     *
     * @return
     */
    @ApiOperation("查询仓库库存列表")
    @GetMapping("/newList")
    public TableDataInfo ckCargoStockList(CkCargoStock ckCargoStock) {
        startPage();
        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();
        queryWrapper.select("sum(cargo_num) as cargo_num",
                "sum(cargo_wt) as cargo_wt",
                "sum(cargo_vol) as cargo_vol"
        ).select(CkCargoStock::getCargoId,
                CkCargoStock::getCargoName,
                CkCargoStock::getCustId,
                CkCargoStock::getCustName,
                CkCargoStock::getCargoSpec,
                CkCargoStock::getOriginCountry,
                CkCargoStock::getHsCode,
                CkCargoStock::getCargoNumber,
                CkCargoStock::getStockDate);
        condition(queryWrapper, ckCargoStock);
        queryWrapper.and(wrapper -> {
            wrapper.gt("cargo_num", 0).or().
            gt("cargo_wt", 0).or().
            gt("cargo_vol", 0);
        });
        queryWrapper.groupBy(CkCargoStock::getCargoId,
                CkCargoStock::getCargoName,
                CkCargoStock::getCustId,
                CkCargoStock::getCustName,
                CkCargoStock::getCargoSpec,
                CkCargoStock::getOriginCountry,
                CkCargoStock::getHsCode,
                CkCargoStock::getCargoNumber,
                CkCargoStock::getStockDate);
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);
        return getDataTable(list);
    }


    /**
     * 查询仓库库存列表
     */
    @ApiOperation("查询仓库库存列表")
    @GetMapping("/list")
    public AjaxResult list(CkCargoStock ckCargoStock) {
        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();
        queryWrapper.select(CkCargoStock::getId, CkCargoStock::getStockDate, CkCargoStock::getCargoNumber,
                CkCargoStock::getItemNumber, CkCargoStock::getBookNumber, CkCargoStock::getExpiryDate, CkCargoStock::getBillNumber,
                CkCargoStock::getVoyageId, CkCargoStock::getVoyageNo, CkCargoStock::getVesselId, CkCargoStock::getVesselName,
                CkCargoStock::getCargoId, CkCargoStock::getHsCode, CkCargoStock::getCargoName,
                CkCargoStock::getBillNo, CkCargoStock::getCargoSpec, CkCargoStock::getOriginCountry, CkCargoStock::getFirstUnit,
                CkCargoStock::getUnitPrice, CkCargoStock::getCurrType, CkCargoStock::getCustId, CkCargoStock::getCustName, CkCargoStock::getOpType,
                CkCargoStock::getTradType, CkCargoStock::getCargoNum, CkCargoStock::getCargoWt, CkCargoStock::getCargoVol, CkCargoStock::getStockId,
                CkCargoStock::getStockCode, CkCargoStock::getStockName, CkCargoStock::getCargoValue, CkCargoStock::getCustomsNo, CkCargoStock::getListNumber,
                CkCargoStock::getRemark, CkCargoStock::getCreateDept, CkCargoStock::getCreateBy, CkCargoStock::getCreateTime, CkCargoStock::getUpdateBy,
                CkCargoStock::getUpdateTime, CkCargoStock::getDelFlag)
                .select(CmCargo::getGdsSeqno)
                .leftJoin(CmCargo.class, CmCargo::getId,CkCargoStock::getCargoId);
        condition(queryWrapper, ckCargoStock);
        if(ckCargoStock.getCustId()!=null){
            queryWrapper.and(qw -> {
                qw.gt(CkCargoStock::getCargoNum, "0")
                        .or().gt(CkCargoStock::getCargoWt, "0")
                        .or().gt(CkCargoStock::getCargoValue, "0")
                        .or().gt(CkCargoStock::getCargoVol, "0");
            });
        }
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);
        return success(list);
    }


    /**
     * 查询某个物品大于0的仓库
     */
    @ApiOperation("查询仓库库存列表")
    @GetMapping("/warehouseList")
    public AjaxResult warehouseList(CkCargoStock ckCargoStock) {
        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();
        condition(queryWrapper, ckCargoStock);
        queryWrapper.and(qw -> {
            qw.gt(CkCargoStock::getCargoNum, "0")
                    .or().gt(CkCargoStock::getCargoWt, "0")
                    .or().gt(CkCargoStock::getCargoValue, "0")
                    .or().gt(CkCargoStock::getCargoVol, "0");
        });
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);
        Map<Long, List<CkCargoStock>> listMap = list.stream().collect(Collectors.groupingBy(CkCargoStock::getStockId));
        List<CkCargoStock> stockList = new ArrayList<>();
        listMap.keySet().forEach(ele -> {
            stockList.add(listMap.get(ele).get(0));
        });
        return success().put("stockList", stockList).put("listMap", listMap);
    }


    /**
     * 查询所有仓库，的库存量
     */
    @ApiOperation("查询仓库库存列表")
    @GetMapping("/stockNumList")
    public AjaxResult stockNumList(CkCargoStock ckCargoStock) {
        List<CmStock> stocks = cmStockService.list(new LambdaQueryWrapper<CmStock>().orderByAsc(CmStock::getStockCode).orderByAsc(CmStock::getStockName));

        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();
        queryWrapper.select("sum(cargo_num) as cargo_num",
                "sum(cargo_wt) as cargo_wt",
                "sum(cargo_value) as cargo_value",
                "sum(cargo_vol) as cargo_vol","stock_Id"
        );
        condition(queryWrapper, ckCargoStock);
        queryWrapper.groupBy(CkCargoStock::getStockId);
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);
        Map<Long, CkCargoStock> map = list.stream()
                .collect(
                        Collectors.toMap(
                                CkCargoStock::getStockId,
                                a -> a)
                );
        stocks.forEach(ele -> {
            ele.setStockId(ele.getId());
            CkCargoStock stock = map.get(ele.getId());
            if (stock != null) {
                ele.setNowStockNum(stock.getCargoNum());
                ele.setNowStockWt(stock.getCargoWt());
                ele.setNowStockVol(stock.getCargoVol());
                ele.setNowCargoValue(stock.getCargoValue());
            } else {
                ele.setNowStockNum(new BigDecimal(0));
                ele.setNowStockWt(new BigDecimal(0));
                ele.setNowStockVol(new BigDecimal(0));
                ele.setNowCargoValue(new BigDecimal(0));
            }
        });
        return success(stocks);
    }


    /**
     * 导出仓库库存列表
     */
    @ApiOperation("导出仓库库存列表")
    @Log(title = "仓库库存导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, CkCargoStock ckCargoStock) {
        MPJLambdaWrapper<CkCargoStock> queryWrapper = new MPJLambdaWrapper();
        condition(queryWrapper, ckCargoStock);
        if (null != ckCargoStock.getBeginDateOut()) {
            queryWrapper.gt(CkCargoStock::getStockDate, ckCargoStock.getBeginDateOut());
        }
        List<CkCargoStock> list = ckCargoStockService.list(queryWrapper);
        List<CkCargoStock> ckCargoStocks = outRecovery(list, ckCargoStock);
        ExcelUtil<CkCargoStock> util = new ExcelUtil<CkCargoStock>(CkCargoStock.class);
        util.exportExcel(response, ckCargoStocks, "仓库库存数据");
    }

    /**
     * 获取仓库库存详细信息
     */
    @ApiOperation("获取仓库库存详细信息")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(ckCargoStockService.getById(id));
    }

    /**
     * 新增仓库库存
     */
    @ApiOperation("新增仓库库存")
    @Log(title = "仓库库存新增", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody CkCargoStock ckCargoStock) {
        return toAjax(ckCargoStockService.save(ckCargoStock));
    }

    /**
     * 修改仓库库存
     */
    @ApiOperation("修改仓库库存")
    @Log(title = "仓库库存修改", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody CkCargoStock ckCargoStock) {
        return toAjax(ckCargoStockService.updateById(ckCargoStock));
    }

    /**
     * 删除仓库库存
     */
    @ApiOperation("删除仓库库存")
    @Log(title = "仓库库存删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids) {
        return toAjax(ckCargoStockService.removeBatchByIds(ids));
    }
    /**
     * 获取商品是否过期，仓库是否过期数据
     */
    @GetMapping("/getIndexMsg")
    public AjaxResult getIndexMsg() {
        AjaxResult result = AjaxResult.success();
        Date date = DateUtils.addDays(new Date(),45);
        LambdaQueryWrapper<CkCargoStock> wrapper = new LambdaQueryWrapper();
        wrapper.lt(CkCargoStock::getExpiryDate,date);
        wrapper.and(wp->{
            wp.gt(CkCargoStock::getCargoNum,0).or()
                    .gt(CkCargoStock::getCargoWt,0).or()
                    .gt(CkCargoStock::getCargoVol,0);
        });
        List<CkCargoStock> cargoStocks = ckCargoStockService.list(wrapper);
        Map<Long,List<CkCargoStock>> cargoStockMap = cargoStocks.stream().collect(Collectors.groupingBy(CkCargoStock::getCargoId));
        StringBuffer cargoStr;
        if(cargoStockMap.keySet().size()>0){
            cargoStr = new StringBuffer("仓库内有：");
        }else{
            cargoStr = new StringBuffer("");
        }
        cargoStockMap.keySet().forEach(ele->{
            List<CkCargoStock> list = cargoStockMap.get(ele);
            cargoStr.append(list.get(0).getCargoName()).append(",");
        });
        if(!cargoStr.toString().equals("")){
            cargoStr.append("这些货物即将到期，请留意。。。");
        }
        result.put("cargoMsg",cargoStr);
        LambdaQueryWrapper<CmWarehouse> warehouseWrapper = new LambdaQueryWrapper();
        warehouseWrapper.lt(CmWarehouse::getValidityEnd,date);
        List<CmWarehouse> warehouses= cmWarehouseService.list(warehouseWrapper);
        if(warehouses.size()>0){
            StringBuffer stockStr = new StringBuffer("您的  ");
            warehouses.forEach(ele->{
                stockStr.append(ele.getStockName()).append(",");
            });
            stockStr.append(" 仓库即将到期，请留意。。。");
            result.put("stockMsg",stockStr);
        }
        return result;
    }

    /**
     * 条件设置
     */
    private void condition(MPJLambdaWrapper<CkCargoStock> queryWrapper, CkCargoStock ckCargoStock) {

        if (null != ckCargoStock.getBeginDate()) {
            queryWrapper.between(CkCargoStock::getStockDate, ckCargoStock.getBeginDate(), ckCargoStock.getEndDate());
        }
        if (null != ckCargoStock.getBeginDateTwo()) {
            queryWrapper.between(CkCargoStock::getExpiryDate, ckCargoStock.getBeginDateTwo(), ckCargoStock.getEndDateTwo());
        }

        if (Validator.isNotEmpty(ckCargoStock.getIsExpire())) {
            queryWrapper.le(CkCargoStock::getExpiryDate, new Date());
        }

        //货物自然序号
        if(Validator.isNotEmpty(ckCargoStock.getCargoNumber())){
            queryWrapper.eq(CkCargoStock::getCargoNumber,ckCargoStock.getCargoNumber());
        }

        //商品料号
        if(Validator.isNotEmpty(ckCargoStock.getItemNumber())){
            queryWrapper.eq(CkCargoStock::getItemNumber,ckCargoStock.getItemNumber());
        }

        //电子账册项号
        if(Validator.isNotEmpty(ckCargoStock.getBookNumber())){
            queryWrapper.eq(CkCargoStock::getBookNumber,ckCargoStock.getBookNumber());
        }

        //报关单号
        if (ckCargoStock.getCustomsNo() != null) {
            queryWrapper.like(CkCargoStock::getCustomsNo, ckCargoStock.getCustomsNo());
        }

        //备案号
        if (ckCargoStock.getGdsSeqno() != null) {
            queryWrapper.eq(CmCargo::getGdsSeqno, ckCargoStock.getGdsSeqno());
        }


        //核注清单号
        if (Validator.isNotEmpty(ckCargoStock.getListNumber())) {
            queryWrapper.like(CkCargoStock::getListNumber, ckCargoStock.getListNumber());
        }


        //单据编号
        if (ckCargoStock.getBillNumber() != null) {
            queryWrapper.like(CkCargoStock::getBillNumber, ckCargoStock.getBillNumber());
        }

        //船舶航次ID
        if (ckCargoStock.getVoyageId() != null) {
            queryWrapper.eq(CkCargoStock::getVoyageId, ckCargoStock.getVoyageId());
        }

        //航次号
        if (Validator.isNotEmpty(ckCargoStock.getVoyageNo())) {
            queryWrapper.like(CkCargoStock::getVoyageNo, ckCargoStock.getVoyageNo());
        }

        //船舶ID
        if (ckCargoStock.getVesselId() != null) {
            queryWrapper.eq(CkCargoStock::getVesselId, ckCargoStock.getVesselId());
        }

        //船舶名称
        if (ckCargoStock.getVesselName() != null) {
            queryWrapper.like(CkCargoStock::getVesselName, ckCargoStock.getVesselName());
        }

        //货物ID
        if (ckCargoStock.getCargoId() != null) {
            queryWrapper.eq(CkCargoStock::getCargoId, ckCargoStock.getCargoId());
        }

        //HS编号
        if (Validator.isNotEmpty(ckCargoStock.getHsCode())) {
            queryWrapper.like(CkCargoStock::getHsCode, ckCargoStock.getHsCode());
        }

        //货物名称
        if (Validator.isNotEmpty(ckCargoStock.getCargoName())) {
            queryWrapper.like(CkCargoStock::getCargoName, ckCargoStock.getCargoName());
        }

        //提运单号
        if (Validator.isNotEmpty(ckCargoStock.getBillNo())) {
            queryWrapper.like(CkCargoStock::getBillNo, ckCargoStock.getBillNo());
        }

        //规格类型品质
        if (Validator.isNotEmpty(ckCargoStock.getCargoSpec())) {
            queryWrapper.like(CkCargoStock::getCargoSpec, ckCargoStock.getCargoSpec());
        }

        //原产国
        if (Validator.isNotEmpty(ckCargoStock.getOriginCountry())) {
            queryWrapper.like(CkCargoStock::getOriginCountry, ckCargoStock.getOriginCountry());
        }

        //货主ID
        if (ckCargoStock.getCustId() != null) {
            queryWrapper.eq(CkCargoStock::getCustId, ckCargoStock.getCustId());
        }

        //货主名称
        if (Validator.isNotEmpty(ckCargoStock.getCustName())) {
            queryWrapper.like(CkCargoStock::getCustName, ckCargoStock.getCustName());
        }

        //业务性质
        if (Validator.isNotEmpty(ckCargoStock.getOpType())) {
            queryWrapper.eq(CkCargoStock::getOpType, ckCargoStock.getOpType());
        }

        //贸易性质
        if (Validator.isNotEmpty(ckCargoStock.getTradType())) {
            queryWrapper.eq(CkCargoStock::getTradType, ckCargoStock.getTradType());
        }

        //货物件数
        if (ckCargoStock.getCargoNum() != null) {
            queryWrapper.gt(CkCargoStock::getCargoNum, ckCargoStock.getCargoNum());
        }

        //货物重量
        if (ckCargoStock.getCargoWt() != null) {
            queryWrapper.gt(CkCargoStock::getCargoWt, ckCargoStock.getCargoWt());
        }

        //货物体积
        if (ckCargoStock.getCargoVol() != null) {
            queryWrapper.gt(CkCargoStock::getCargoVol, ckCargoStock.getCargoVol());
        }

        //库场ID
        if (ckCargoStock.getStockId() != null) {
            queryWrapper.eq(CkCargoStock::getStockId, ckCargoStock.getStockId());
        }

        //库场代码
        if (Validator.isNotEmpty(ckCargoStock.getStockCode())) {
            queryWrapper.like(CkCargoStock::getStockCode, ckCargoStock.getStockCode());
        }

        //库场名称
        if (Validator.isNotEmpty(ckCargoStock.getStockName())) {
            queryWrapper.like(CkCargoStock::getStockName, ckCargoStock.getStockName());
        }

        //备注
        if (Validator.isNotEmpty(ckCargoStock.getRemark())) {
            queryWrapper.eq(CkCargoStock::getRemark, ckCargoStock.getRemark());
        }

        //删除标志（0代表存在 2代表删除）
        if (Validator.isNotEmpty(ckCargoStock.getDelFlag())) {
            queryWrapper.eq(CkCargoStock::getDelFlag, ckCargoStock.getDelFlag());
        }


        //租户ID
        if (Validator.isNotEmpty(ckCargoStock.getTenantId())) {
            queryWrapper.eq(CkCargoStock::getTenantId, ckCargoStock.getTenantId());
        }

    }

}
