package net.lab1024.sa.admin.module.business.wms.base.item.service.impl;

import cn.idev.excel.FastExcel;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.wms.base.item.domain.entity.ItemEntity;
import net.lab1024.sa.admin.module.business.wms.base.item.domain.form.ItemAddForm;
import net.lab1024.sa.admin.module.business.wms.base.item.domain.form.ItemUpdateForm;
import net.lab1024.sa.admin.module.business.wms.base.item.domain.form.ItemsImportForm;
import net.lab1024.sa.admin.module.business.wms.base.item.manager.ItemManager;
import net.lab1024.sa.admin.module.business.wms.base.item.service.ItemQueryService;
import net.lab1024.sa.admin.module.business.wms.base.item.service.ItemService;
import net.lab1024.sa.admin.util.JoinerResult;
import net.lab1024.sa.admin.util.ResponseDTOUtil;
import net.lab1024.sa.admin.util.ValidateDictKeyUtil;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.module.support.dict.constant.DictConst;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ItemServiceImpl implements ItemService {

    @Resource
    private ItemManager itemManager;

    @Resource
    private ItemQueryService itemQueryService;

    @Resource
    private ValidateDictKeyUtil validateDictKeyUtil;

    /**
     * 添加
     *
     * @param addForm 入参
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> add(ItemAddForm addForm) {
        ItemEntity existingItem = itemQueryService.queryByItemCode(addForm.getItemCode());
        if (existingItem != null) {
            return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, UserErrorCode.ALREADY_EXIST.getMsg());
        }
        ItemEntity itemEntity = SmartBeanUtil.copy(addForm, ItemEntity.class);
        itemManager.save(itemEntity);
        return ResponseDTO.ok();
    }

    /**
     * 更新
     *
     * @param updateForm 入参
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> update(ItemUpdateForm updateForm) {
        ItemEntity existingItem = itemQueryService.queryByItemCode(updateForm.getItemCode());
        if (existingItem != null && !existingItem.getItemId().equals(updateForm.getItemId())) {
            return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, UserErrorCode.ALREADY_EXIST.getMsg());
        }
        ItemEntity itemEntity = SmartBeanUtil.copy(updateForm, ItemEntity.class);
        //更新并更新缓存
        itemManager.update(itemEntity);
        return ResponseDTO.ok();
    }

    /**
     * 批量删除
     *
     * @param idList 入参
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> batchDelete(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }
        //批量删除并删除缓存
        itemManager.batchDelete(idList);
        return ResponseDTO.ok();
    }

    /**
     * 单个删除
     *
     * @param itemId 入参
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> delete(Long itemId) {
        if (null == itemId) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }
        //单个删除并删除缓存
        itemManager.deleteById(itemId);
        return ResponseDTO.ok();
    }

    /**
     * 物料导入
     *
     * @param file 上传文件
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> importItems(MultipartFile file) {
        List<ItemsImportForm> dataList;
        try {
            dataList = FastExcel.read(file.getInputStream()).head(ItemsImportForm.class)
                    .sheet()
                    .doReadSync();
        } catch (IOException e) {
            throw new BusinessException("数据格式存在问题，无法读取");
        }
        if (CollectionUtils.isEmpty(dataList)) {
            return ResponseDTO.userErrorParam("数据为空");
        }

        //获取所物料类型
        List<String> itemTypes = dataList.stream().map(ItemsImportForm::getItemType).toList();

        //验证物料类型
        Map<String, String> itemTypeMap = validateDictKeyUtil.validateDictCodes(itemTypes, DictConst.ITEM_TYPE.getValue());

        //获取所有包装单位
        List<String> units = dataList.stream().map(ItemsImportForm::getUnit).toList();

        //验证包装单位
        Map<String, String> unitMap = validateDictKeyUtil.validateDictCodes(units, DictConst.ITEM_UNIT.getValue());

        //获取所有物料
        List<String> itemCodes = dataList.stream().map(ItemsImportForm::getItemCode).toList();

        //查询数据库存在的物料
        Map<String, ItemEntity> exitItemMap = itemQueryService.queryByItemCodesToMap(itemCodes);

        List<ItemEntity> insertToItem = new ArrayList<>();
        List<ItemEntity> updateToItem = new ArrayList<>();
        for (ItemsImportForm itemsImportForm : dataList) {

            //物料类型
            String itemType = itemTypeMap.get(itemsImportForm.getItemType());

            //包装单位
            String unit = unitMap.get(itemsImportForm.getUnit());

            //物料
            ItemEntity item = exitItemMap.get(itemsImportForm.getItemCode());

            //物料为空则新增，否则更新
            if (item == null) {
                insertToItem.add(createItem(itemsImportForm.getItemCode(), itemsImportForm.getItemName(), unit, BigDecimal.ONE, itemType));
            } else {
                updateToItem.add(createItem(itemsImportForm.getItemCode(), itemsImportForm.getItemName(), unit, BigDecimal.ONE, itemType));
            }
        }
        JoinerResult resultMsg = JoinerResult.createJoiner();
        return ResponseDTOUtil.buildResponseDTO(insertToItem, updateToItem, itemManager::saveBatch, itemManager::batchUpdate, resultMsg);
    }

    /**
     * 创建物料
     *
     * @param itemCode   物料编码
     * @param itemName   物料名称
     * @param unit       包装单位
     * @param packFactor 包装系数
     * @param itemType   物料类型
     * @return ItemEntity
     */
    public ItemEntity createItem(String itemCode, String itemName, String unit, BigDecimal packFactor, String itemType) {
        return ItemEntity.builder()
                .itemCode(itemCode)
                .itemName(itemName)
                .unit(unit)
                .packFactor(packFactor)
                .disabledFlag(true)
                .itemType(itemType)
                .createUserId(SmartRequestUtil.getRequestUser().getUserId())
                .createUserName(SmartRequestUtil.getRequestUser().getUserName())
                .build();
    }
}
