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.WarehouseInventory;
import com.ruoyi.web.stock.domain.WarehouseStockIssue;
import com.ruoyi.web.stock.domain.WarehouseStockIssueGoods;
import com.ruoyi.web.stock.domain.vo.InventoryLineOptionVo;
import com.ruoyi.web.stock.mapper.WarehouseInventoryMapper;
import com.ruoyi.web.stock.mapper.WarehouseStockIssueMapper;
import com.ruoyi.web.stock.service.IWarehouseStockIssueService;
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 WarehouseStockIssueServiceImpl implements IWarehouseStockIssueService {
    @Autowired private WarehouseStockIssueMapper warehouseStockIssueMapper;
    @Autowired private WarehouseInventoryMapper warehouseInventoryMapper;

    @Override
    public WarehouseStockIssue selectById(Long id) {
        WarehouseStockIssue entity = warehouseStockIssueMapper.selectById(id);
        if (entity != null) entity.setGoodsList(warehouseStockIssueMapper.selectGoodsByIssueId(id));
        return entity;
    }

    @Override
    public List<WarehouseStockIssue> selectList(WarehouseStockIssue query) {
        return warehouseStockIssueMapper.selectList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submitIssue(WarehouseStockIssue entity, String operator) {
        validateSubmit(entity);
        if (StringUtils.isEmpty(entity.getIssueUser())) entity.setIssueUser(operator);
        entity.setSheetNo(generateSheetNo(entity.getOrgId(), entity.getSheetDate()));
        entity.setCreateBy(operator);
        entity.setUpdateBy(operator);
        entity.setDelFlag("0");
        entity.setTotalSubtotal(BigDecimal.ZERO);
        warehouseStockIssueMapper.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<>();
        BigDecimal totalSubtotal = BigDecimal.ZERO;
        for (WarehouseStockIssueGoods line : entity.getGoodsList()) {
            if (line.getSourceInventoryId() == null) throw new ServiceException("提交失败，存在未选择源库存行的明细");
            if (!seenSource.add(line.getSourceInventoryId())) throw new ServiceException("提交失败，同一源库存行不能重复领料");
            WarehouseInventory src = warehouseInventoryMapper.selectWarehouseInventoryById(line.getSourceInventoryId());
            if (src == null || !entity.getOrgId().equals(src.getOrgId()) || !"0".equals(src.getDelFlag())) {
                throw new ServiceException("提交失败，源库存行不存在或无权操作");
            }

            BigDecimal baseQty = defaultZero(line.getBaseQty());
            BigDecimal assistQty = defaultZero(line.getAssistantQty());
            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("提交失败，领料数量超过源仓可用库存");
            }

            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("提交失败，源仓扣减库存失败");

            BigDecimal processingFee = defaultZero(line.getProcessingFee());
            BigDecimal subtotal = baseQty.multiply(processingFee).setScale(4, RoundingMode.HALF_UP);
            totalSubtotal = totalSubtotal.add(subtotal);

            line.setIssueId(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.setBaseQty(baseQty);
            line.setAssistantQty(assistQty);
            line.setProcessingFee(processingFee);
            line.setSubtotal(subtotal);
            line.setCreateBy(operator);
            line.setUpdateBy(operator);
            line.setDelFlag("0");
            fillFromOptMap(lineOptMap, line);
        }

        warehouseStockIssueMapper.insertGoodsBatch(entity.getGoodsList());
        warehouseStockIssueMapper.updateTotalSubtotal(entity.getId(), totalSubtotal, operator);
        return 1;
    }

    private void fillFromOptMap(Map<Long, InventoryLineOptionVo> lineOptMap, WarehouseStockIssueGoods 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) {
        warehouseStockIssueMapper.deleteGoodsByIssueId(id, operator);
        return warehouseStockIssueMapper.deleteById(id, operator);
    }

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

    private void validateSubmit(WarehouseStockIssue entity) {
        if (entity == null) throw new ServiceException("提交失败，参数不能为空");
        if (entity.getSheetDate() == 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 sheetDate) {
        String dateText = new SimpleDateFormat("yyyyMMdd").format(sheetDate);
        Integer maxSeq = warehouseStockIssueMapper.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;
    }
}
