package com.sifang.modules.supply.stock.service;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sunshine.SystemSetting.utils.Result;
import com.sifang.modules.supply.order.dao.MaterialDeliverDao;
import com.sifang.modules.supply.setting.entity.CrmSupplyWarehouse;
import com.sifang.modules.supply.stock.dao.MaterialStockDao;
import com.sifang.modules.supply.stock.dao.MaterialStockWarningDao;
import com.sifang.modules.supply.stock.dao.SupplyMaterialDao;
import com.sifang.modules.supply.stock.entity.MaterialStockWarning;
import com.sifang.modules.supply.stock.entity.MaterialWarehouseStocks;
import com.sifang.modules.supply.stock.entity.SupplyMaterial;
import com.sifang.modules.supply.stock.request.AddStockReq;
import com.sifang.modules.supply.stock.request.AddStockVo;
import com.sifang.modules.supply.stock.request.MaterialStockSaveReq;
import com.sifang.modules.supply.warehouse.dao.CrmSupplyMaterialKeepDao;
import com.sifang.modules.supply.warehouse.dao.SupplyMaterialBatchDao;
import com.sifang.modules.supply.warehouse.entity.CrmSupplyInventoryOrderDetail;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.IdGen;
import com.sifang.modules.sys.entity.Operator;
import com.sifang.modules.sys.util.LayuiPage;
import com.sifang.modules.sys.util.SqlBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author hongzq
 */
@Service
public class MaterialStockService extends BaseService {

    @Autowired
    MaterialStockDao materialStockDao;

    @Autowired
    MaterialStockWarningDao stockWarningDao;

    @Autowired
    private SupplyMaterialDao materialDao;

    @Autowired
    private MaterialDeliverDao materialDeliverDao;

    @Autowired
    private CrmSupplyMaterialKeepDao supplyMaterialKeepDao;

    public MaterialWarehouseStocks getById(String id) {
        return materialStockDao.get(id);
    }

    public LayuiPage<Record> stockListPage(LayuiPage<Record> page, Map<String,String> map){
        page.setData(materialStockDao.stockList(page,map));
        page.setCount(materialStockDao.countStockList(map));
        return page;
    }

    /**
     * 代理商库存列表数据
     */
    public LayuiPage<Record> stockListPageForTrader(LayuiPage<Record> page, Map<String,String> map){
        List<Record> records = materialStockDao.stockListForTrader(page, map);
        setCommonDate(records);
        page.setData(records);
        page.setCount(materialStockDao.countStockListForTrader(map));
        return page;
    }

    public List<Record> getStockListForTrader(Map<String,String> map){
        List<Record> records = materialStockDao.getStockListForTrader(map);
        setCommonDate(records);
        return records;
    }

    public void setCommonDate(List<Record> records){
        for (Record record : records) {
            String warehouseId = record.getStr("warehouse_id");
            String materialId = record.getStr("material_id");
            //待发货数量 status=5
            BigDecimal waitDeliverCount = materialDeliverDao.findMaterialCount(warehouseId,materialId,"5");
            record.set("waitDeliverNum",waitDeliverCount);
            //待签收 status=6,11
            BigDecimal waitSignCount = materialDeliverDao.findMaterialCount(warehouseId,materialId,"6,11");
            record.set("waitSignCount",waitSignCount);

            Record countList = supplyMaterialKeepDao.findMaterialCount(materialId, warehouseId);
            //累计已安装
            BigDecimal yazTotalCapacity = countList.getBigDecimal("yazTotalCapacity");
            record.set("yazTotalCapacity",yazTotalCapacity);
            //累计已发电
            BigDecimal yfdTotalCapacity = countList.getBigDecimal("yfdTotalCapacity");
            record.set("yfdTotalCapacity",yfdTotalCapacity);
            //累计已投放
            BigDecimal ytfTotalCapacity = countList.getBigDecimal("ytfTotalCapacity");
            record.set("ytfTotalCapacity",ytfTotalCapacity);
            //安装未发电
            BigDecimal azwfdTotalCapacity = yazTotalCapacity.subtract(yfdTotalCapacity);
            record.set("azwfdTotalCapacity",azwfdTotalCapacity);
            //安装未投放
            BigDecimal azwtfTotalCapacity = yazTotalCapacity.subtract(ytfTotalCapacity);
            record.set("azwtfTotalCapacity",azwtfTotalCapacity);
            //可用总库存 金额
            BigDecimal totalPrice = record.getBigDecimal("price1").add(record.getBigDecimal("price2")).add(record.getBigDecimal("price3")).add(record.getBigDecimal("price4"));
            record.set("totalPrice",totalPrice);
            //累计已发货 合计
            BigDecimal total1 = BigDecimal.ZERO;
            if (record.getBigDecimal("yfhTotalCapacity") != null) {
                total1 = record.getBigDecimal("yfhTotalCapacity").add(record.getBigDecimal("yk_yfh_amount"));
            }else {
                total1= record.getBigDecimal("yk_yfh_amount");
            }
            record.set("total1",total1);
            //累计已安装 合计
            BigDecimal total2 = BigDecimal.ZERO;
            if (record.getBigDecimal("yazTotalCapacity") != null){
                total2 = record.getBigDecimal("yazTotalCapacity").add(record.getBigDecimal("yk_yaz_amount"));
            }else {
                total2 = record.getBigDecimal("yk_yaz_amount");
            }
            record.set("total2",total2);
            //累计已发电 合计
            BigDecimal total3 = BigDecimal.ZERO;
            if (record.getBigDecimal("yfdTotalCapacity") != null){
                total3 = record.getBigDecimal("yfdTotalCapacity").add(record.getBigDecimal("yk_yfd_amount"));
            }else {
                total3 = record.getBigDecimal("yk_yfd_amount");
            }
            record.set("total3",total3);
            if (record.getBigDecimal("yfhTotalCapacity") == null){
                record.set("yfhTotalCapacity",BigDecimal.ZERO);
            }
        }
    }

    public Record findStockInfoById(String id) {
        Map<String, String> map = new HashMap<>();
        map.put("id", id);
        List<Record> stockList = materialStockDao.stockList(null, map);
        if (!stockList.isEmpty()) {
            return stockList.get(0);
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveMaterialStockInfo(MaterialStockSaveReq req){
        MaterialWarehouseStocks warehouseStocks = materialStockDao.get(req.getId());
        materialStockDao.save(warehouseStocks);

        BigDecimal stockWarning = req.getLowStockWarning();
        MaterialStockWarning warning = stockWarningDao.findByMaterialIdAndAscriptionId(warehouseStocks.getMaterialId(),
                warehouseStocks.getAscriptionId());
        if (warning != null) {
            warning.setLowStockWarning(stockWarning);
        } else {
            warning = new MaterialStockWarning();
            warning.setMaterialId(warehouseStocks.getMaterialId());
            warning.setType(warehouseStocks.getType());
            warning.setAscriptionId(warehouseStocks.getAscriptionId());
            warning.setAscriptionName(warehouseStocks.getAscriptionName());
            warning.setLowStockWarning(stockWarning);
        }
        stockWarningDao.save(warning);
    }

    /**
     * 盘盈入库
     * 可用数量+  实际数量+ 已入库数量+
     */
    public MaterialWarehouseStocks updateStockForInStock(String materialId, CrmSupplyWarehouse warehouse, BigDecimal amount, String type, String userId, CrmSupplyInventoryOrderDetail detail) {
        MaterialWarehouseStocks stocks = findByWarehouse(materialId, warehouse.getId());

        // 仓库归属 1.供应链(平台) 2.经销商 3.供应商
        String sType = ("1".equals(warehouse.getType())) ? "1" : ("2".equals(warehouse.getType())?"3":"2");
        if(stocks==null){
            stocks=new MaterialWarehouseStocks();
            stocks.setMaterialId(materialId);
            stocks.setWarehouseId(warehouse.getId());
            // type 归属 1.供应链 2.供应商 3.代理商
            stocks.setType(sType);
            stocks.setAscriptionId(warehouse.getAscriptionId());
            stocks.setAscriptionName(warehouse.getAscriptionName());
            stocks.setWarning(amount);
            stocks.setRealNum(amount);
            stocks.setTotal(amount);
            stocks.setCreateBy(userId);
            stocks.setCreateTime(new Date());
            stocks.setNewestStorageTime(new Date());
            stocks.setCostPrice(detail.getCostPrice());
            stocks.setBdSalePrice(detail.getBdSalePrice());
        }else{
            stocks.setWarning(stocks.getWarning().add(amount));
            stocks.setRealNum(stocks.getRealNum().add(amount));
            stocks.setTotal(stocks.getTotal().add(amount));
            stocks.setNewestStorageTime(new Date());

        }

        materialStockDao.save(stocks);
        return stocks;
    }

    public MaterialWarehouseStocks updateStockForInStocks(MaterialWarehouseStocks stocks, String materialId,
                                                          CrmSupplyWarehouse warehouse, String userId,BigDecimal price,BigDecimal subtract) {
        // 仓库归属 1.供应链(平台) 2.经销商 3.供应商
        String sType = ("1".equals(warehouse.getType())) ? "1" : ("2".equals(warehouse.getType())?"3":"2");
        if(stocks==null){
            stocks=new MaterialWarehouseStocks();
            stocks.setMaterialId(materialId);
            stocks.setWarehouseId(warehouse.getId());
            // type 归属 1.供应链 2.供应商 3.代理商
            stocks.setType(sType);
            stocks.setAscriptionId(warehouse.getAscriptionId());
            stocks.setAscriptionName(warehouse.getAscriptionName());
            stocks.setWarning(subtract);
            stocks.setRealNum(subtract);
            stocks.setTotal(subtract);
            stocks.setCreateBy(userId);
            stocks.setCreateTime(new Date());
            stocks.setNewestStorageTime(new Date());
            stocks.setCostPrice(BigDecimal.ZERO);
            stocks.setBdSalePrice(price);
        }else{
            stocks.setWarning(stocks.getWarning().add(subtract));
            stocks.setRealNum(stocks.getRealNum().add(subtract));
            stocks.setTotal(stocks.getTotal().add(subtract));
            stocks.setNewestStorageTime(new Date());

        }
        materialStockDao.save(stocks);
        return stocks;
    }

    /**
     * 盘亏出库
     * 可用数量-  实际数量- 已出库数量+
     */
    public MaterialWarehouseStocks updateStockForOutStock(String materialId, String warehouseId, BigDecimal amount) {
        MaterialWarehouseStocks stocks = findByWarehouse(materialId, warehouseId);
        stocks.setWarning(stocks.getWarning().subtract(amount));
        stocks.setRealNum(stocks.getRealNum().subtract(amount));
        stocks.setNewestKeepTime(new Date());
        materialStockDao.save(stocks);
        return stocks;
    }


    public List<Record> frozeStockDetail(String materialId, String warehouseId){
        //发货单的
        SqlBuilder builder = new SqlBuilder();
        builder.line("select o.id, o.number, o.place_name, o.remarks, d.apply_amount, d.out_amount, o.place_time, '1' as orderType, o.status")
                .line("from crm_supply_material_deliver_order_detail d")
                .line("inner join crm_supply_material_deliver_order o on d.main_id=o.id ")
                .line("where d.material_id=? and o.out_warehouse_id=?", materialId, warehouseId)
                .line("and o.status in ('5')");
        List<Record> list = Db.find(builder.build(), builder.params());
        //调拨单的
        builder = new SqlBuilder();
        builder.line("select o.id, o.code as number, o.creator as place_name, o.remarks, d.inout_amount, o.create_time as place_time, '2' as orderType, o.status")
                .line("from crm_supply_allocation_order_detail d")
                .line("inner join crm_supply_allocation_order o on d.inventory_id=o.id")
                .line("where d.material_id=? and o.warehouse_id=?", materialId, warehouseId)
                .line("and o.status in ('2', '3')");
        List<Record> dbList = Db.find(builder.build(), builder.params());
        list.addAll(dbList);
        return list;
    }

    public MaterialWarehouseStocks findByWarehouse(String materialId, String warehouseId) {
        return materialStockDao.findByWarehouse(materialId, warehouseId);
    }

    /**
     *
     * @param ascriptionId 归属id
     * @param warehouseId 所属仓库id
     * @param materialId 物料id
     * @param amount 冻结数量
     * @return 物料库存
     *  增加出库冻结数量 减少可用数量
     */
    public MaterialWarehouseStocks addFrozeOutNum(String ascriptionId, String warehouseId, String materialId, BigDecimal amount) {
        MaterialWarehouseStocks stock = materialStockDao.getStock(ascriptionId, warehouseId, materialId);
        if (!StrKit.notNull(stock)) {
            SupplyMaterial material = materialDao.get(materialId);
            throw new BusinessException("物料["+material.getCode()+"]库存不足");
        } else if (stock.getWarning().compareTo(amount) < 0) {
            SupplyMaterial material = materialDao.get(materialId);
            throw new BusinessException("物料["+material.getCode()+"]库存不足");
        }
        stock.setFrozeOutNum(stock.getFrozeOutNum().add(amount));
        stock.setWarning(stock.getWarning().subtract(amount));
        materialStockDao.save(stock);
        return stock;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result addStock(AddStockVo vo, Operator operator){
        List<AddStockReq> details = vo.getDetails();
        int i = 1;
        for (AddStockReq req : details) {
            MaterialWarehouseStocks materialWarehouseStocks = materialStockDao.findByWarehouse(req.getMaterialId(), vo.getWarehouseId());
            if (materialWarehouseStocks != null){
                throw new IllegalArgumentException("第"+i+"行物料已存在，请勿重复添加");
            }
            MaterialWarehouseStocks stock = new MaterialWarehouseStocks();
            stock.setMaterialId(req.getMaterialId());
            stock.setWarehouseId(vo.getWarehouseId());
            stock.setType("3");
            stock.setAscriptionId(vo.getTraderId());
            stock.setAscriptionName(vo.getTraderName());
            stock.setCreateTime(new Date());
            stock.setCreateBy(operator.getUserId());
            stock.setYkYazAmount(req.getYkYazAmount());
            stock.setYkYfhAmount(req.getYkYfhAmount());
            stock.setYkYfdAmount(req.getYkYfdAmount());
            stock.setYkThAmount(req.getYkThAmount());
            stock.setYkMdAmount(req.getYkMdAmount());
            stock.setCostPrice(BigDecimal.ZERO);
            materialStockDao.save(stock);
            i++;
        }

        return Result.ok();
    }
}
