package com.zg.project.wisdom.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils;
import com.zg.common.utils.EntityFillUtils;
import com.zg.common.utils.SecurityUtils;
import com.zg.project.wisdom.domain.RkInfo;
import com.zg.project.wisdom.domain.dto.MoveRequestDTO;
import com.zg.project.wisdom.domain.dto.MoveTargetItem;
import com.zg.project.wisdom.mapper.MoveRecordMapper;
import com.zg.project.wisdom.domain.MoveRecord;
import com.zg.project.wisdom.mapper.RkInfoMapper;
import com.zg.project.wisdom.service.IMoveRecordService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 移库记录Service业务层处理
 * 
 * @author zg
 * @date 2025-06-20
 */
@Service
public class MoveRecordServiceImpl implements IMoveRecordService 
{
    @Autowired
    private MoveRecordMapper moveRecordMapper;

    @Autowired
    private RkInfoMapper rkInfoMapper;

    /**
     * 查询移库记录
     * 
     * @param id 移库记录主键
     * @return 移库记录
     */
    @Override
    public MoveRecord selectMoveRecordById(Long id)
    {
        return moveRecordMapper.selectMoveRecordById(id);
    }

    /**
     * 查询移库记录列表
     * 
     * @param moveRecord 查询条件
     * @return 移库记录
     */
    @Override
    public List<MoveRecord> selectMoveRecordList(MoveRecord moveRecord)
    {
        return moveRecordMapper.selectMoveRecordList(moveRecord);
    }

    /**
     * 新增移库记录
     * 
     * @param moveRecord 移库记录
     * @return 结果
     */

    /**
     * 修改移库记录
     * 
     * @param moveRecord 移库记录
     * @return 结果
     */
    @Override
    public int updateMoveRecord(MoveRecord moveRecord)
    {
        return moveRecordMapper.updateMoveRecord(moveRecord);
    }

    /**
     * 批量删除移库记录
     * 
     * @param ids 需要删除的移库记录主键
     * @return 结果
     */
    @Override
    public int deleteMoveRecordByIds(Long[] ids)
    {
        return moveRecordMapper.deleteMoveRecordByIds(ids);
    }

    /**
     * 删除移库记录信息
     * 
     * @param id 移库记录主键
     * @return 结果
     */
    @Override
    public int deleteMoveRecordById(Long id)
    {
        return moveRecordMapper.deleteMoveRecordById(id);
    }

    /**
     * 处理库存移库操作
     *
     * @param dto 移库请求参数（包含原库存ID、移库目标列表等）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processMove(MoveRequestDTO dto) {
        // 查询原始库存记录
        RkInfo original = rkInfoMapper.selectRkInfoById(dto.getFromRkId());
        if (original == null || "1".equals(original.getIsDelete())) {
            throw new ServiceException("原库存不存在或已删除");
        }

        // 计算目标总数量
        BigDecimal totalQty = dto.getTargets().stream()
                .map(MoveTargetItem::getRealQty)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 原始库存数量
        BigDecimal realQty = original.getRealQty();
        if (realQty == null) {
            throw new ServiceException("原库存数量为空，无法进行比较");
        }

        if (totalQty.compareTo(realQty) > 0) {
            throw new ServiceException("拆分总数量不能大于原库存数量");
        }

        // 操作信息
        String username = dto.getMovedBy();
        Date now = DateUtils.parseDate(dto.getMovedAt());

        // 情况一：整库移库（目标总数量 = 原库存，且仅一个目标）
        if (dto.getTargets().size() == 1 && totalQty.compareTo(realQty) == 0) {
            MoveTargetItem target = dto.getTargets().get(0);

            RkInfo info = new RkInfo();
            BeanUtils.copyProperties(original, info);

            original.setCangku(target.getToCangku());
            original.setPcode(target.getToPcode());
            original.setTrayCode(target.getToTrayCode());
            original.setHasMoved("1");
            original.setUpdateBy(username);
            original.setUpdateTime(now);
            rkInfoMapper.updateRkInfo(original);

            // 记录移库日志
            moveRecordMapper.insertMoveRecord(createMoveRecord(info, target, dto));
            return;
        }

        // 情况二 & 三：需要新建多条库存记录
        List<RkInfo> insertList = new ArrayList<>();

        // 情况三：部分移库（目标总量 < 原库存）
        if (totalQty.compareTo(realQty) < 0) {
            // 原库存数量减少
            original.setRealQty(realQty.subtract(totalQty));
            original.setUpdateBy(username);
            original.setUpdateTime(now);
            rkInfoMapper.updateRkInfo(original);
        } else {
            // 情况二：原库存刚好用完（但目标多个） → 删除原库存
            rkInfoMapper.deleteRkInfoById(original.getId());
        }

        // 新增多条目标库存
        for (MoveTargetItem target : dto.getTargets()) {
            RkInfo newInfo = new RkInfo();
            BeanUtils.copyProperties(original, newInfo, "id");

            newInfo.setCangku(target.getToCangku());
            newInfo.setPcode(target.getToPcode());
            newInfo.setTrayCode(target.getToTrayCode());
            newInfo.setRealQty(target.getRealQty());
            newInfo.setHasMoved("1");

            newInfo.setCreateBy(username);
            newInfo.setCreateTime(now);
            newInfo.setUpdateBy(username);
            newInfo.setUpdateTime(now);

            insertList.add(newInfo);

            // 移库记录
            moveRecordMapper.insertMoveRecord(createMoveRecord(original, target, dto));
        }

        if (!insertList.isEmpty()) {
            rkInfoMapper.batchInsertRkInfo(insertList);
        }
    }

    /**
     * 构建移库记录对象
     *
     * @param info 原库存记录
     * @param target   目标位置数据
     * @param dto      请求参数
     * @return 构建后的移库记录
     */
    private MoveRecord createMoveRecord(RkInfo info, MoveTargetItem target, MoveRequestDTO dto) {
        Long userId = SecurityUtils.getUserId();
        MoveRecord record = new MoveRecord();
        record.setRkId(info.getId());
        record.setEntityId(info.getEntityId());
        record.setFromCangku(info.getCangku());
        record.setFromPcode(info.getPcode());
        record.setFromTrayCode(info.getTrayCode());
        record.setToCangku(target.getToCangku());
        record.setToPcode(target.getToPcode());
        record.setToTrayCode(target.getToTrayCode());
        record.setMoveReason(dto.getMoveReason());
        record.setMovedBy(userId.toString());
        record.setMovedAt(DateUtils.getNowDate());

        record.setIsDelete("0");
        record.setCreateBy(userId.toString());
        record.setUpdateBy(userId.toString());
        record.setCreateTime(DateUtils.getNowDate());
        record.setUpdateTime(DateUtils.getNowDate());

        return record;
    }

}
