package net.lab1024.sa.admin.module.business.base.stock.service;

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;

import cn.idev.excel.FastExcel;
import net.lab1024.sa.admin.constant.UsageStatusEnum;
import net.lab1024.sa.admin.module.business.base.item.domain.entity.ItemEntity;
import net.lab1024.sa.admin.module.business.base.item.domain.form.ItemsImportForm;
import net.lab1024.sa.admin.module.business.base.location.dao.LocationDao;
import net.lab1024.sa.admin.module.business.base.location.domain.entity.LocationEntity;
import net.lab1024.sa.admin.module.business.base.location.service.LocationQueryService;
import net.lab1024.sa.admin.module.business.base.location.service.LocationService;
import net.lab1024.sa.admin.module.business.base.stock.dao.StockDao;
import net.lab1024.sa.admin.module.business.base.stock.domain.entity.StockEntity;
import net.lab1024.sa.admin.module.business.base.stock.domain.form.StockAddForm;
import net.lab1024.sa.admin.module.business.base.stock.domain.form.StockUpdateForm;
import net.lab1024.sa.admin.module.business.base.stock.domain.form.StocksImportForm;
import net.lab1024.sa.admin.module.business.base.stock.manager.StockManager;
import net.lab1024.sa.admin.util.JoinerResult;
import net.lab1024.sa.admin.util.ResponseDTOUtils;
import net.lab1024.sa.admin.util.ValidateDictKey;
import net.lab1024.sa.base.common.code.SystemErrorCode;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.domain.ResponseDTO;
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 jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * 容器信息 Service
 *
 * @author 霍锦
 * @since 2024-11-26 11:37:48
 * copyright 友仓
 */

@Service
public class StockService {

    @Resource
    private StockDao stockDao;

    @Resource
    private LocationDao locationDao;

    @Resource
    private StockManager stockManager;

    @Resource
    private ValidateDictKey ValidateDictKey;

    @Resource
    private StockQueryService stockQueryService;

    @Resource
    private LocationService locationService;


    /**
     * 添加
     *
     * @param addForm 添加参数
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> add(StockAddForm addForm) {
        StockEntity existingStock = stockQueryService.queryByStockCode(addForm.getStockCode());
        if (existingStock != null) {
            return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, UserErrorCode.ALREADY_EXIST.getMsg());
        }
        StockEntity stockEntity = SmartBeanUtil.copy(addForm, StockEntity.class);
        stockDao.insert(stockEntity);

        //更新缓存
        stockManager.removeCache();
        return ResponseDTO.ok();
    }

    /**
     * 更新
     *
     * @param updateForm 更新参数
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> update(StockUpdateForm updateForm) {
        StockEntity existingStock = stockQueryService.queryByStockCode(updateForm.getStockCode());
        if (existingStock != null && !existingStock.getStockId().equals(updateForm.getStockId())) {
            return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, UserErrorCode.ALREADY_EXIST.getMsg());
        }
        //当前更新的容器的库位
        if (existingStock != null && existingStock.getLocationId() != null) {
            //更新库位状态
            locationService.updateLocationStatus(existingStock.getLocationId(), UsageStatusEnum.FREE.getValue());
        }

        if (updateForm.getLocationId() != null) {
            LocationEntity location = locationDao.selectById(updateForm.getLocationId());
            StockEntity curStock = stockQueryService.queryStockByLocationId(updateForm.getLocationId());
            if (curStock != null && existingStock != null) {
                if (!curStock.getStockId().equals(existingStock.getStockId())) {
                    return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, location.getLocationCode() + "库位绑定的当前容器为" + curStock.getStockCode());
                }
            }
            //更新库位状态
            locationService.updateLocationStatus(updateForm.getLocationId(), UsageStatusEnum.USED.getValue());
        }
        StockEntity stockEntity = SmartBeanUtil.copy(updateForm, StockEntity.class);
        stockDao.updateById(stockEntity);

        //更新缓存
        stockManager.removeCache();
        return ResponseDTO.ok();
    }

    /**
     * 批量删除
     *
     * @param idList id集合
     * @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());
        }

        //批量删除
        stockManager.removeBatchByIds(idList);

        //更新缓存
        stockManager.removeCache();
        return ResponseDTO.ok();
    }

    /**
     * 单个删除
     *
     * @param stockId 容器Id
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> delete(Long stockId) {
        if (null == stockId) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }

        stockDao.deleteById(stockId);

        //更新缓存
        stockManager.removeCache();
        return ResponseDTO.ok();
    }

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

        //获取所有去重后的容器类型
        List<String> stockTypes = dataList.stream().map(StocksImportForm::getStockType).distinct().collect(Collectors.toList());

        //验证容器类型
        Map<String, String> itemTypeMap = ValidateDictKey.validateDictCodes(stockTypes, DictConst.STOCK_TYPE.getValue());

        //获取所有去重后的容器编码
        List<String> stockCodes = dataList.stream().map(StocksImportForm::getStockCode).distinct().collect(Collectors.toList());

        //查询数据库存在的容器
        Map<String, StockEntity> exitStockMap = stockQueryService.queryStockListToMap(stockCodes);

        List<StockEntity> insertToStock = new ArrayList<>();
        List<StockEntity> updateToStock = new ArrayList<>();
        for (StocksImportForm stocksImportForm : dataList) {

            //容器类型
            String stockType = itemTypeMap.get(stocksImportForm.getStockType());

            //容器
            StockEntity stock = exitStockMap.get(stocksImportForm.getStockCode());

            //容器为空新增，否则更新
            if (stock == null) {
                insertToStock.add(createStock(stocksImportForm.getStockCode(), stockType));
            } else {
                updateToStock.add(createStock(stocksImportForm.getStockCode(), stockType));
            }
        }

        JoinerResult resultMsg = JoinerResult.createJoiner();
        return ResponseDTOUtils.buildResponseSussDTO(insertToStock, updateToStock, stockManager::saveBatch, stockManager::updateBatchById, resultMsg);
    }

    /**
     * 创建容器
     *
     * @param stockCode 容器编码
     * @param stockType 容器类型
     * @return StockEntity
     */
    public StockEntity createStock(String stockCode, String stockType) {
        return StockEntity.builder()
                .stockCode(stockCode)
                .stockType(stockType)
                .status(UsageStatusEnum.FREE.getValue())
                .disabledFlag(true)
                .createUserId(SmartRequestUtil.getRequestUser().getUserId())
                .createUserName(SmartRequestUtil.getRequestUser().getUserName())
                .build();
    }
}
