package com.ruoyi.web.stock.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.stock.domain.WarehouseBase;
import com.ruoyi.web.stock.domain.WarehouseInventory;
import com.ruoyi.web.stock.domain.WarehouseStockTransfer;
import com.ruoyi.web.stock.domain.WarehouseStockTransferGoods;
import com.ruoyi.web.stock.domain.vo.InventoryLineOptionVo;
import com.ruoyi.web.stock.mapper.WarehouseBaseMapper;
import com.ruoyi.web.stock.mapper.WarehouseInventoryMapper;
import com.ruoyi.web.stock.mapper.WarehouseStockTransferMapper;
import com.ruoyi.web.stock.service.IWarehouseStockTransferService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 调拨：源仓扣减、目标仓增加；成本按源行「基本库存」比例结转。
 */
@Service
public class WarehouseStockTransferServiceImpl implements IWarehouseStockTransferService {

    @Autowired
    private WarehouseStockTransferMapper warehouseStockTransferMapper;
    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;
    @Autowired
    private WarehouseBaseMapper warehouseBaseMapper;

    @Override
    public WarehouseStockTransfer selectById(Long id) {
        WarehouseStockTransfer entity = warehouseStockTransferMapper.selectById(id);
        if (entity != null) {
            entity.setGoodsList(warehouseStockTransferMapper.selectGoodsByTransferId(id));
        }
        return entity;
    }

    @Override
    public List<WarehouseStockTransfer> selectList(WarehouseStockTransfer query) {
        return warehouseStockTransferMapper.selectList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submitTransfer(WarehouseStockTransfer entity, String operator) {
        validateSubmit(entity);
        if (StringUtils.isEmpty(entity.getTransferUser())) {
            entity.setTransferUser(operator);
        }
        entity.setSheetNo(generateSheetNo(entity.getOrgId(), entity.getTransferDate()));
        entity.setCreateBy(operator);
        entity.setUpdateBy(operator);
        entity.setDelFlag("0");
        warehouseStockTransferMapper.insert(entity);

        List<InventoryLineOptionVo> lineOpts = warehouseInventoryMapper.selectInventoryLinesForStockCheck(entity.getOrgId());
        Map<Long, InventoryLineOptionVo> lineOptMap = new HashMap<>();
        for (InventoryLineOptionVo opt : lineOpts) {
            lineOptMap.put(opt.getInventoryId(), opt);
        }

        Set<Long> seenSource = new HashSet<>();
        List<WarehouseStockTransferGoods> lines = entity.getGoodsList();

        for (WarehouseStockTransferGoods line : lines) {
            if (line.getSourceInventoryId() == null) {
                throw new ServiceException("提交失败，存在未选择源库存行的明细");
            }
            if (!seenSource.add(line.getSourceInventoryId())) {
                throw new ServiceException("提交失败，同一源库存行不能重复调拨");
            }
            if (StringUtils.isEmpty(line.getInWarehouseNo())) {
                throw new ServiceException("提交失败，入库仓库不能为空");
            }
            String inWhNo = line.getInWarehouseNo().trim();

            WarehouseInventory src = warehouseInventoryMapper.selectWarehouseInventoryById(line.getSourceInventoryId());
            if (src == null || !entity.getOrgId().equals(src.getOrgId()) || !"0".equals(src.getDelFlag())) {
                throw new ServiceException("提交失败，源库存行不存在或无权操作");
            }
            if (inWhNo.equals(src.getWarehouseNo())) {
                throw new ServiceException("提交失败，入库仓库不能与出库仓库相同（物料：" + src.getGoodsNum() + "）");
            }

            WarehouseBase whIn = warehouseBaseMapper.selectWarehouseBaseByNo(inWhNo, entity.getOrgId());
            if (whIn == null) {
                throw new ServiceException("提交失败，入库仓库不存在：" + inWhNo);
            }

            BigDecimal baseQty = defaultZero(line.getBaseQty());
            BigDecimal assistQty = defaultZero(line.getAssistQty());
            if (baseQty.compareTo(BigDecimal.ZERO) <= 0 && assistQty.compareTo(BigDecimal.ZERO) <= 0) {
                throw new ServiceException("提交失败，调拨基本数量与辅助数量不能同时小于等于0");
            }

            BigDecimal bookBase = defaultZero(src.getStockQty());
            BigDecimal bookAssist = defaultZero(src.getAssistStockQty());
            if (baseQty.compareTo(bookBase) > 0 || assistQty.compareTo(bookAssist) > 0) {
                throw new ServiceException("提交失败，调拨数量超过源仓可用库存（物料：" + src.getGoodsNum() + "）");
            }

            BigDecimal bookCost = defaultZero(src.getCostAmount());
            BigDecimal costShare = BigDecimal.ZERO;
            if (bookBase.compareTo(BigDecimal.ZERO) > 0) {
                costShare = baseQty.multiply(bookCost).divide(bookBase, 4, RoundingMode.HALF_UP);
            }

            int outRows = warehouseInventoryMapper.increaseInventory(
                src.getId(), baseQty.negate(), assistQty.negate(), costShare.negate(), operator);
            if (outRows == 0) {
                throw new ServiceException("提交失败，源仓扣减库存失败");
            }

            WarehouseInventory tgt = warehouseInventoryMapper.selectByUniqueKey(
                entity.getOrgId(), inWhNo, src.getGoodsNum(), src.getBatchNo());
            if (tgt == null) {
                WarehouseInventory add = new WarehouseInventory();
                add.setOrgId(entity.getOrgId());
                add.setWarehouseNo(inWhNo);
                add.setWarehouseName(whIn.getWarehouseName());
                add.setGoodsNum(src.getGoodsNum());
                add.setGoodsName(src.getGoodsName());
                add.setBatchNo(src.getBatchNo());
                add.setStockQty(baseQty);
                add.setAssistStockQty(assistQty);
                add.setCostAmount(costShare);
                add.setDelFlag("0");
                add.setCreateBy(operator);
                add.setUpdateBy(operator);
                warehouseInventoryMapper.insertWarehouseInventory(add);
            } else {
                int inRows = warehouseInventoryMapper.increaseInventory(
                    tgt.getId(), baseQty, assistQty, costShare, operator);
                if (inRows == 0) {
                    throw new ServiceException("提交失败，目标仓增加库存失败");
                }
            }

            line.setTransferId(entity.getId());
            line.setSheetNo(entity.getSheetNo());
            line.setOrgId(entity.getOrgId());
            line.setGoodsNum(src.getGoodsNum());
            line.setGoodsName(src.getGoodsName());
            line.setBatchNo(src.getBatchNo());
            line.setOutWarehouseNo(src.getWarehouseNo());
            line.setOutWarehouseName(src.getWarehouseName());
            line.setInWarehouseNo(inWhNo);
            line.setInWarehouseName(whIn.getWarehouseName());
            line.setBaseQty(baseQty);
            line.setAssistQty(assistQty);
            line.setCreateBy(operator);
            line.setUpdateBy(operator);
            line.setDelFlag("0");
            fillFromOptMap(lineOptMap, line);
        }

        warehouseStockTransferMapper.insertGoodsBatch(lines);
        return 1;
    }

    private void fillFromOptMap(Map<Long, InventoryLineOptionVo> lineOptMap, WarehouseStockTransferGoods line) {
        InventoryLineOptionVo opt = lineOptMap.get(line.getSourceInventoryId());
        if (opt == null) {
            return;
        }
        if (StringUtils.isNotEmpty(opt.getGoodsSpec())) {
            line.setGoodsSpec(opt.getGoodsSpec());
        }
        if (StringUtils.isEmpty(line.getBaseUnit())) {
            line.setBaseUnit(opt.getBaseUnit());
        }
        if (StringUtils.isEmpty(line.getAssistantUnit())) {
            line.setAssistantUnit(opt.getAssistantUnit());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Long id, String operator) {
        warehouseStockTransferMapper.deleteGoodsByTransferId(id, operator);
        return warehouseStockTransferMapper.deleteById(id, operator);
    }

    @Override
    public List<InventoryLineOptionVo> listInventoryLineOptions(String orgId) {
        return warehouseInventoryMapper.selectInventoryLinesForStockCheck(orgId);
    }

    private void validateSubmit(WarehouseStockTransfer entity) {
        if (entity == null) {
            throw new ServiceException("提交失败，参数不能为空");
        }
        if (entity.getTransferDate() == null) {
            throw new ServiceException("提交失败，调拨日期不能为空");
        }
        if (StringUtils.isEmpty(entity.getOrgId())) {
            throw new ServiceException("提交失败，企业标识不能为空");
        }
        if (entity.getGoodsList() == null || entity.getGoodsList().isEmpty()) {
            throw new ServiceException("提交失败，至少需要一条明细");
        }
    }

    private String generateSheetNo(String orgId, Date transferDate) {
        String dateText = new SimpleDateFormat("yyyyMMdd").format(transferDate);
        Integer maxSeq = warehouseStockTransferMapper.selectTodayMaxSeq(orgId, dateText);
        int nextSeq = (maxSeq == null ? 0 : maxSeq) + 1;
        return dateText + String.format("%04d", nextSeq);
    }

    private static BigDecimal defaultZero(BigDecimal v) {
        return v == null ? BigDecimal.ZERO : v;
    }
}
