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.WarehouseStockAdjust;
import com.ruoyi.web.stock.domain.WarehouseStockAdjustGoods;
import com.ruoyi.web.stock.domain.vo.InventoryLineOptionVo;
import com.ruoyi.web.stock.mapper.WarehouseInventoryMapper;
import com.ruoyi.web.stock.mapper.WarehouseStockAdjustMapper;
import com.ruoyi.web.stock.service.IWarehouseStockAdjustService;
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;

/**
 * 仓库调整：明细中的基本/辅助数量为<strong>增减量</strong>（可正可负），提交后累加到当前库存；
 * 成本按「调整基本数量 × 单位成本」累加到 cost_amount。
 */
@Service
public class WarehouseStockAdjustServiceImpl implements IWarehouseStockAdjustService {

    @Autowired
    private WarehouseStockAdjustMapper warehouseStockAdjustMapper;
    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Override
    public WarehouseStockAdjust selectById(Long id) {
        WarehouseStockAdjust entity = warehouseStockAdjustMapper.selectById(id);
        if (entity != null) {
            entity.setGoodsList(warehouseStockAdjustMapper.selectGoodsByAdjustId(id));
        }
        return entity;
    }

    @Override
    public List<WarehouseStockAdjust> selectList(WarehouseStockAdjust query) {
        return warehouseStockAdjustMapper.selectList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submitAdjust(WarehouseStockAdjust entity, String operator) {
        validateSubmit(entity);
        if (StringUtils.isEmpty(entity.getAdjustUser())) {
            entity.setAdjustUser(operator);
        }
        entity.setSheetNo(generateSheetNo(entity.getOrgId(), entity.getAdjustDate()));
        entity.setTotalAmount(BigDecimal.ZERO);
        entity.setCreateBy(operator);
        entity.setUpdateBy(operator);
        entity.setDelFlag("0");
        warehouseStockAdjustMapper.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> seenInventory = new HashSet<>();
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<WarehouseStockAdjustGoods> lines = entity.getGoodsList();

        for (WarehouseStockAdjustGoods line : lines) {
            if (line.getInventoryId() == null) {
                throw new ServiceException("提交失败，存在未选择库存行的明细");
            }
            if (!seenInventory.add(line.getInventoryId())) {
                throw new ServiceException("提交失败，同一库存行不能重复调整");
            }

            BigDecimal adjBase = defaultZero(line.getAdjBaseQty());
            BigDecimal adjAssist = defaultZero(line.getAdjAssistQty());
            if (adjBase.compareTo(BigDecimal.ZERO) == 0 && adjAssist.compareTo(BigDecimal.ZERO) == 0) {
                throw new ServiceException("提交失败，调整基本数量与调整辅助数量不能同时为0");
            }

            WarehouseInventory inv = warehouseInventoryMapper.selectWarehouseInventoryById(line.getInventoryId());
            if (inv == null || !entity.getOrgId().equals(inv.getOrgId()) || !"0".equals(inv.getDelFlag())) {
                throw new ServiceException("提交失败，库存行不存在或无权操作");
            }

            BigDecimal bookBase = defaultZero(inv.getStockQty());
            BigDecimal bookAssist = defaultZero(inv.getAssistStockQty());
            BigDecimal newBase = bookBase.add(adjBase);
            BigDecimal newAssist = bookAssist.add(adjAssist);
            if (newBase.compareTo(BigDecimal.ZERO) < 0 || newAssist.compareTo(BigDecimal.ZERO) < 0) {
                throw new ServiceException("提交失败，调整后库存不能为负数（物料：" + inv.getGoodsNum() + "）");
            }

            BigDecimal unitCost = defaultZero(line.getUnitCost());
            BigDecimal lineAmount = adjBase.multiply(unitCost).setScale(4, RoundingMode.HALF_UP);

            int updated = warehouseInventoryMapper.increaseInventory(inv.getId(), adjBase, adjAssist, lineAmount, operator);
            if (updated == 0) {
                throw new ServiceException("提交失败，更新库存失败");
            }

            line.setAdjustId(entity.getId());
            line.setSheetNo(entity.getSheetNo());
            line.setOrgId(entity.getOrgId());
            line.setGoodsNum(inv.getGoodsNum());
            line.setGoodsName(inv.getGoodsName());
            line.setBatchNo(inv.getBatchNo());
            line.setWarehouseNo(inv.getWarehouseNo());
            line.setWarehouseName(inv.getWarehouseName());
            line.setAdjBaseQty(adjBase);
            line.setAdjAssistQty(adjAssist);
            line.setUnitCost(unitCost);
            line.setLineAmount(lineAmount);
            line.setCreateBy(operator);
            line.setUpdateBy(operator);
            line.setDelFlag("0");
            fillUnitsFromMap(lineOptMap, line);
            totalAmount = totalAmount.add(lineAmount);
        }

        warehouseStockAdjustMapper.insertGoodsBatch(lines);
        warehouseStockAdjustMapper.updateTotalAmount(entity.getId(), totalAmount, operator);
        entity.setTotalAmount(totalAmount);
        return 1;
    }

    private void fillUnitsFromMap(Map<Long, InventoryLineOptionVo> lineOptMap, WarehouseStockAdjustGoods line) {
        InventoryLineOptionVo opt = lineOptMap.get(line.getInventoryId());
        if (opt == null) {
            return;
        }
        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) {
        warehouseStockAdjustMapper.deleteGoodsByAdjustId(id, operator);
        return warehouseStockAdjustMapper.deleteById(id, operator);
    }

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

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