/*
 * Copyright ©2023 CJB-CNIT Team. All rights reserved
 */
package com.openhis.web.datadictionary.appservice.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.core.domain.entity.SysDictData;
import com.core.common.enums.DeleteFlag;
import com.core.common.utils.*;
import com.core.common.utils.bean.BeanUtils;
import com.core.common.utils.poi.ExcelUtil;
import com.core.system.service.ISysDictTypeService;
import com.openhis.administration.domain.ChargeItemDefinition;
import com.openhis.administration.domain.DeviceDefinition;
import com.openhis.administration.domain.Location;
import com.openhis.administration.domain.Supplier;
import com.openhis.administration.service.IChargeItemDefinitionService;
import com.openhis.administration.service.IDeviceDefinitionService;
import com.openhis.administration.service.ILocationService;
import com.openhis.administration.service.ISupplierService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.utils.CommonUtil;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.sys.service.IOperationRecordService;
import com.openhis.web.datadictionary.appservice.IDeviceManageAppService;
import com.openhis.web.datadictionary.appservice.IItemDefinitionService;
import com.openhis.web.datadictionary.dto.*;
import com.openhis.web.datadictionary.mapper.DeviceManageMapper;
import com.openhis.workflow.domain.DeviceRequest;
import com.openhis.workflow.service.IDeviceRequestService;
import com.openhis.workflow.service.ISupplyRequestService;
import com.openhis.yb.service.YbManager;

/**
 * 器材目录 impl
 *
 * @author
 * @date 2025-03-17
 */
@Service
public class DeviceManageAppServiceImpl implements IDeviceManageAppService {

    @Resource
    private ISupplyRequestService supplyRequestService;

    @Resource
    private IDeviceDefinitionService deviceDefinitionService;

    @Resource
    private IChargeItemDefinitionService chargeItemDefinitionService;

    @Resource
    private ILocationService locationService;

    @Resource
    private DeviceManageMapper deviceManageMapper;

    @Resource
    private ISysDictTypeService sysDictTypeService;

    @Resource
    private IItemDefinitionService itemDefinitionServic;

    @Resource
    private ISupplierService supplierService;

    @Resource
    private AssignSeqUtil assignSeqUtil;

    @Resource
    private YbManager ybService;

    @Resource
    private IOperationRecordService operationRecordService;

    @Resource
    private IDeviceRequestService deviceRequestService;

    /**
     * 器材目录初始化
     *
     * @return
     */
    @Override
    public R<?> getDeviceManageInit() {

        DeviceManageInitDto deviceManageInitDto = new DeviceManageInitDto();

        // 获取状态
        List<DeviceManageInitDto.statusEnumOption> statusEnumOptions = Stream.of(PublicationStatus.values())
            .map(status -> new DeviceManageInitDto.statusEnumOption(status.getValue(), status.getInfo()))
            .collect(Collectors.toList());
        deviceManageInitDto.setStatusFlagOptions(statusEnumOptions);

        // // 获取执行科室
        // LambdaQueryWrapper<Organization> queryWrapper = new LambdaQueryWrapper<>();
        // queryWrapper.eq(Organization::getTypeEnum, OrganizationType.HOSPITAL_DEPARTMENT);
        // List<Organization> organizations = organizationService.list(queryWrapper);
        // List<DeviceManageInitDto.exeOrganization> exeOrganizations = organizations.stream()
        // .map(exeOrg -> new DeviceManageInitDto.exeOrganization(exeOrg.getId(), exeOrg.getName()))
        // .collect(Collectors.toList());
        // deviceManageInitDto.setExeOrganizations(exeOrganizations);
        // // 从枚举中获取器材分类
        // List<DeviceManageInitDto.deviceCategory> deviceCategories = Stream.of(DeviceCategory.values())
        // .map(category -> new DeviceManageInitDto.deviceCategory(category.getValue(), category.getInfo()))
        // .collect(Collectors.toList());
        // deviceManageInitDto.setDeviceCategories(deviceCategories);

        // 获取器材
        List<SysDictData> deviceList =
            sysDictTypeService.selectDictDataByType(CommonConstants.DictName.DEVICE_CATEGORY_CODE);
        // 从字典中获取器材分类
        List<DeviceManageInitDto.dictCategoryCode> deviceCategories = deviceList.stream()
            .map(category -> new DeviceManageInitDto.dictCategoryCode(category.getDictValue(), category.getDictLabel()))
            .collect(Collectors.toList());
        deviceManageInitDto.setDeviceCategories(deviceCategories);

        // 获取医保是否对码
        List<DeviceManageInitDto.statusEnumOption> statusYBWeatherOption = Stream.of(Whether.values())
            .map(status -> new DeviceManageInitDto.statusEnumOption(status.getValue(), status.getInfo()))
            .collect(Collectors.toList());
        deviceManageInitDto.setStatusYBWeatherOptions(statusYBWeatherOption);

        // 查询供应商列表
        List<Supplier> supplierList = supplierService.getList();
        // 供应商信息
        List<DeviceManageInitDto.supplierListOption> supplierListOptions = supplierList.stream()
            .map(supplier -> new DeviceManageInitDto.supplierListOption(supplier.getId(), supplier.getName()))
            .collect(Collectors.toList());
        deviceManageInitDto.setSupplierListOptions(supplierListOptions);

        return R.ok(deviceManageInitDto);
    }

    /**
     * 器材目录查询
     *
     * @param
     * @param searchKey 查询条件-模糊查询
     * @param pageNo 查询条件
     * @param pageSize 查询条件
     * @return 器材目录查询结果
     */
    @Override
    public R<?> getDevicePage(DeviceManageSelParam deviceManageSelParam, String searchKey, Integer pageNo,
        Integer pageSize, HttpServletRequest request) {

        // 构建查询条件
        QueryWrapper<DeviceManageDto> queryWrapper = HisQueryUtils.buildQueryWrapper(deviceManageSelParam, searchKey,
            new HashSet<>(Arrays.asList("bus_no", "name", "py_str", "wb_str")), request);

        // 分页查询
        IPage<DeviceManageDto> deviceManagePage =
            deviceManageMapper.getDevicePage(new Page<>(pageNo, pageSize), queryWrapper);

        deviceManagePage.getRecords().forEach(e -> {
            // 高值器材标志枚举类回显赋值
            e.setHvcmFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getHvcmFlag()));
            // 医保标记枚举类回显赋值
            e.setYbFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getYbFlag()));
            // 医保对码标记枚举类回显赋值
            e.setYbMatchFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getYbMatchFlag()));
            // 过敏标记枚举类回显赋值
            e.setAllergenFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getAllergenFlag()));
            // 器材分类
            // e.setCategoryEnum_enumText(EnumUtils.getInfoByValue(DeviceCategory.class, e.getCategoryEnum()));

            // 器材状态
            e.setStatusEnum_enumText(EnumUtils.getInfoByValue(PublicationStatus.class, e.getStatusEnum()));
        });

        // 返回【器材目录列表DTO】分页
        return R.ok(deviceManagePage);
    }

    /**
     * 编辑器材信息
     *
     * @param deviceManageDto 器材信息
     */
    @Override
    public R<?> editDevice(DeviceManageUpDto deviceManageDto) {
        DeviceDefinition deviceDefinition = new DeviceDefinition();
        BeanUtils.copyProperties(deviceManageDto, deviceDefinition);
        // 拼音码
        deviceDefinition.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(deviceDefinition.getName()));
        // 五笔码
        deviceDefinition.setWbStr(ChineseConvertUtils.toWBFirstLetter(deviceDefinition.getName()));

        // 更新器材信息
        if (deviceDefinitionService.updateById(deviceDefinition)) {

            // 调用医保目录对照接口
            String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
            if (Whether.YES.getCode().equals(ybSwitch) && StringUtils.isNotEmpty(deviceDefinition.getYbNo())) {
                R<?> r =
                    ybService.directoryCheck(CommonConstants.TableName.ADM_DEVICE_DEFINITION, deviceDefinition.getId());
                if (200 != r.getCode()) {
                    throw new RuntimeException("医保目录对照接口异常");
                }
            }

            ChargeItemDefinition chargeItemDefinition = new ChargeItemDefinition();
            chargeItemDefinition.setYbType(deviceManageDto.getYbType()).setTypeCode(deviceManageDto.getItemTypeCode())
                .setInstanceTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
                .setInstanceId(deviceDefinition.getId()).setPrice(deviceManageDto.getRetailPrice())
                .setChargeName(deviceManageDto.getName());;
            // 插入操作记录
            operationRecordService.addEntityOperationRecord(DbOpType.UPDATE.getCode(),
                CommonConstants.TableName.ADM_DEVICE_DEFINITION, deviceDefinition);
            // 更新价格表
            boolean upItemDef = itemDefinitionServic.updateItem(chargeItemDefinition);

            // 更新子表,修改购入价,条件:采购
            boolean upItemDetail1 = itemDefinitionServic.updateItemDetail(chargeItemDefinition,
                deviceManageDto.getPurchasePrice(), ConditionCode.PURCHASE.getCode());
            // 更新子表,修改零售价,条件:单位
            boolean upItemDetail2 = itemDefinitionServic.updateItemDetail(chargeItemDefinition,
                deviceManageDto.getRetailPrice(), ConditionCode.UNIT.getCode());
            // 更新子表,修改最高零售价,条件:限制
            boolean upItemDetail3 = itemDefinitionServic.updateItemDetail(chargeItemDefinition,
                deviceManageDto.getMaximumRetailPrice(), ConditionCode.LIMIT.getCode());

            // 更新价格表
            return upItemDef && upItemDetail1 && upItemDetail2 && upItemDetail3
                ? R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"器材目录"}))
                : R.fail(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        return R.fail(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
    }

    /**
     * 器材目录详细查询
     *
     * @param id 查询条件
     * @return 器材目录查询结果
     */
    @Override
    public R<?> getDeviceOne(@RequestParam Long id) {
        // 获取租户ID
        Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
        // 根据ID查询【器材目录】
        DeviceManageDto deviceManageDto = deviceManageMapper.getOne(id, tenantId);
        return R.ok(deviceManageDto);
    }

    /**
     * 器材目录停用
     *
     * @param ids 器材目录ID列表
     * @return
     */
    @Override
    public R<?> editDeviceStop(List<Long> ids) {
        List<DeviceDefinition> DeviceDefinitionList = new CopyOnWriteArrayList<>();
        // 取得更新值
        for (Long detail : ids) {
            DeviceDefinition deviceDefinition = new DeviceDefinition();
            deviceDefinition.setId(detail);
            deviceDefinition.setStatusEnum(PublicationStatus.RETIRED.getValue());
            DeviceDefinitionList.add(deviceDefinition);
        }
        // 插入操作记录
        operationRecordService.addIdsOperationRecord(DbOpType.STOP.getCode(),
            CommonConstants.TableName.ADM_DEVICE_DEFINITION, ids);

        // 更新器材信息
        return deviceDefinitionService.updateBatchById(DeviceDefinitionList)
            ? R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"器材目录"}))
            : R.fail(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
    }

    /**
     * 器材目录启用
     *
     * @param ids 器材目录ID列表
     * @return
     */
    @Override
    public R<?> editDeviceStart(List<Long> ids) {
        List<DeviceDefinition> DeviceDefinitionList = new CopyOnWriteArrayList<>();
        // 取得更新值
        for (Long detail : ids) {
            DeviceDefinition DeviceDefinition = new DeviceDefinition();
            DeviceDefinition.setId(detail);
            DeviceDefinition.setStatusEnum(PublicationStatus.ACTIVE.getValue());
            DeviceDefinitionList.add(DeviceDefinition);
        }
        // 插入操作记录
        operationRecordService.addIdsOperationRecord(DbOpType.START.getCode(),
            CommonConstants.TableName.ADM_DEVICE_DEFINITION, ids);

        // 更新器材信息
        return deviceDefinitionService.updateBatchById(DeviceDefinitionList)
            ? R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"器材目录"}))
            : R.fail(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
    }

    /**
     * 添加供应商信息
     *
     * @param deviceManageUpDto 供应商信息
     */
    @Override
    public R<?> addDevice(@Validated @RequestBody DeviceManageUpDto deviceManageUpDto) {
        DeviceDefinition deviceDefinition = new DeviceDefinition();
        BeanUtils.copyProperties(deviceManageUpDto, deviceDefinition);
        // 使用10位数基础采番
        String code = assignSeqUtil.getSeq(AssignSeqEnum.DEVICE_NUM.getPrefix(), 10);
        deviceDefinition.setBusNo(code);
        // 拼音码
        deviceDefinition.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(deviceDefinition.getName()));
        // 五笔码
        deviceDefinition.setWbStr(ChineseConvertUtils.toWBFirstLetter(deviceDefinition.getName()));
        // 新增外来器材目录
        deviceDefinition.setStatusEnum(PublicationStatus.ACTIVE.getValue());
        if (deviceDefinitionService.addDevice(deviceDefinition)) {
            // 调用医保目录对照接口
            String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
            if (Whether.YES.getCode().equals(ybSwitch) && StringUtils.isNotEmpty(deviceDefinition.getYbNo())) {
                R<?> r =
                    ybService.directoryCheck(CommonConstants.TableName.ADM_DEVICE_DEFINITION, deviceDefinition.getId());
                if (200 != r.getCode()) {
                    throw new RuntimeException("医保目录对照接口异常");
                }
            }
            // 插入操作记录
            operationRecordService.addEntityOperationRecord(DbOpType.INSERT.getCode(),
                CommonConstants.TableName.ADM_DEVICE_DEFINITION, deviceDefinition);

            ItemUpFromDirectoryDto itemUpFromDirectoryDto = new ItemUpFromDirectoryDto();
            BeanUtils.copyProperties(deviceManageUpDto, itemUpFromDirectoryDto);
            itemUpFromDirectoryDto.setTypeCode(deviceManageUpDto.getItemTypeCode())
                .setInstanceTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
                .setEffectiveStart(DateUtils.getNowDate()).setStatusEnum(PublicationStatus.ACTIVE.getValue())
                .setConditionFlag(Whether.YES.getValue()).setChargeName(deviceManageUpDto.getName())
                .setInstanceId(deviceDefinition.getId()).setPrice(deviceManageUpDto.getRetailPrice());

            return itemDefinitionServic.addItem(itemUpFromDirectoryDto)
                ? R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"器材目录"}))
                : R.fail(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00008, null));
        }
        return R.fail(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00008, null));
    }

    /**
     * 导入器材目录
     *
     * @param file 文件
     * @return 结果
     */
    @Override
    public R<?> importData(MultipartFile file) {
        // 读取文件
        R<List<DeviceImportDto>> readResult = CommonUtil.readImportedExcelFile(file, DeviceImportDto.class);
        if (R.SUCCESS != readResult.getCode()) {
            return readResult;
        }
        List<DeviceImportDto> importDtoList = readResult.getData();
        // 导入信息校验
        R<?> validateResult = validateImportDtoList(importDtoList);
        if (R.SUCCESS != validateResult.getCode()) {
            return validateResult;
        }
        // 查询机构ID、位置信息供后续使用
        Long orgId = SecurityUtils.getLoginUser().getOrgId();
        List<Location> locationList = locationService.list(new LambdaQueryWrapper<Location>()
            .eq(Location::getDeleteFlag, DeleteFlag.NOT_DELETED.getCode()).orderByAsc(Location::getId));
        Long defaultLocationId = locationList.stream().findFirst().orElse(new Location()).getId();
        Map<String, List<Location>> locationNameMap =
            locationList.stream().collect(Collectors.groupingBy(Location::getName));
        // 创建表数据
        for (DeviceImportDto importDto : importDtoList) {
            // 创建器材定义
            DeviceDefinition deviceDefinition =
                createDeviceDefinitionEntity(importDto, orgId, defaultLocationId, locationNameMap);
            deviceDefinitionService.save(deviceDefinition);
            // 创建费用定价和详情
            chargeItemDefinitionService.addChargeItemDefinitionAndDetail(importDto.getName(), importDto.getTypeCode(),
                importDto.getYbType(), importDto.getUnitCode(), importDto.getPurchasePrice(),
                importDto.getRetailPrice(), importDto.getMaximumRetailPrice(), orgId,
                CommonConstants.TableName.ADM_DEVICE_DEFINITION, deviceDefinition.getId());
        }
        return R.ok(null, "导入成功！");
    }

    /**
     * 获取导入模板
     *
     * @param response 响应
     */
    @Override
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<DeviceImportDto> util = new ExcelUtil<>(DeviceImportDto.class);
        util.importTemplateExcel(response, "器材目录数据");
    }

    /**
     * 校验耗材是否可以编辑
     *
     * @param deviceId 耗材ID
     * @return 校验结果
     */
    @Override
    public R<?> validateDeviceEdit(Long deviceId) {
        List<DeviceRequest> deviceRequestList = deviceRequestService.getDevRequestByDeviceId(deviceId);
        if (!deviceRequestList.isEmpty()) {
            if (deviceRequestList.stream()
                .allMatch(x -> x.getStatusEnum().equals(RequestStatus.COMPLETED.getValue()))) {
                return R.ok(1, "医生开过该耗材，不可编辑");
            } else {
                // 校验是否可以编辑
                boolean result = supplyRequestService.verifyAbleEdit(deviceId);
                if (result) {
                    return R.ok(2, "该耗材已经入库过，不可编辑");
                }
            }
        }
        return R.ok();
    }

    /**
     * 导入信息校验
     *
     * @param importDtoList 器材目录导入数据列表
     */
    private R<?> validateImportDtoList(List<DeviceImportDto> importDtoList) {
        // 字段校验（必填及数值类型）
        List<String> fieldValidateMsgList = new ArrayList<>();
        for (int i = 0; i < importDtoList.size(); i++) {
            DeviceImportDto importDto = importDtoList.get(i);
            importDto.setLineNumber(i + 2);
            List<String> lineValidateMsgList = new ArrayList<>();
            if (StringUtils.isEmpty(importDto.getName())) {
                lineValidateMsgList.add("器材名称必填");
            }
            if (StringUtils.isEmpty(importDto.getCategoryCode())) {
                lineValidateMsgList.add("器材分类必填");
            }
            if (StringUtils.isEmpty(importDto.getUnitCode())) {
                lineValidateMsgList.add("包装单位必填");
            }
            if (StringUtils.isEmpty(importDto.getSize())) {
                lineValidateMsgList.add("包装规格必填");
            }
            if (StringUtils.isEmpty(importDto.getItemMinQuantityStr())) {
                lineValidateMsgList.add("最小库存警戒数量(常规单位)必填");
            }
            BigDecimal itemMinQuantity;
            try {
                itemMinQuantity = new BigDecimal(importDto.getItemMinQuantityStr());
                importDto.setItemMinQuantity(itemMinQuantity);
            } catch (Exception e) {
                lineValidateMsgList.add("最小库存警戒数量(常规单位)应为数值类型");
            }
            if (StringUtils.isEmpty(importDto.getItemMaxQuantityStr())) {
                lineValidateMsgList.add("最大库存警戒数量(常规单位)必填");
            }
            BigDecimal itemMaxQuantity;
            try {
                itemMaxQuantity = new BigDecimal(importDto.getItemMaxQuantityStr());
                importDto.setItemMaxQuantity(itemMaxQuantity);
            } catch (Exception e) {
                lineValidateMsgList.add("最大库存警戒数量(常规单位)应为数值类型");
            }
            if (StringUtils.isEmpty(importDto.getPartPercentStr())) {
                lineValidateMsgList.add("拆零比必填");
            }
            BigDecimal partPercent;
            try {
                partPercent = new BigDecimal(importDto.getPartPercentStr());
                importDto.setPartPercent(partPercent);
            } catch (Exception e) {
                lineValidateMsgList.add("拆零比应为数值类型");
            }
            if (StringUtils.isEmpty(importDto.getLocationName())) {
                lineValidateMsgList.add("所在位置名称必填");
            }
            if (StringUtils.isEmpty(importDto.getHvcmFlag())) {
                lineValidateMsgList.add("高值器材标志必填");
            }
            if (StringUtils.isEmpty(importDto.getYbFlag())) {
                lineValidateMsgList.add("医保标记必填");
            }
            if (StringUtils.isEmpty(importDto.getYbMatchFlag())) {
                lineValidateMsgList.add("医保对码标记必填");
            }
            if (Whether.YES.getCode().equals(importDto.getYbMatchFlag()) && StringUtils.isEmpty(importDto.getYbNo())) {
                lineValidateMsgList.add("医保对码时，医保编码必填");
            }
            if (StringUtils.isEmpty(importDto.getAllergenFlag())) {
                lineValidateMsgList.add("过敏标记必填");
            }
            if (StringUtils.isEmpty(importDto.getRxFlag())) {
                lineValidateMsgList.add("处方标志必填");
            }
            if (StringUtils.isEmpty(importDto.getTypeCode())) {
                lineValidateMsgList.add("财务类别必填");
            }
            if (StringUtils.isEmpty(importDto.getYbType())) {
                lineValidateMsgList.add("医保费用类别必填");
            }
            if (StringUtils.isEmpty(importDto.getPurchasePriceStr())) {
                lineValidateMsgList.add("购入价必填");
            }
            BigDecimal purchasePrice;
            try {
                purchasePrice = new BigDecimal(importDto.getPurchasePriceStr());
                importDto.setPurchasePrice(purchasePrice);
            } catch (Exception e) {
                lineValidateMsgList.add("购入价应为数值类型");
            }
            if (StringUtils.isEmpty(importDto.getRetailPriceStr())) {
                lineValidateMsgList.add("零售价必填");
            }
            BigDecimal retailPrice;
            try {
                retailPrice = new BigDecimal(importDto.getRetailPriceStr());
                importDto.setRetailPrice(retailPrice);
            } catch (Exception e) {
                lineValidateMsgList.add("零售价应为数值类型");
            }
            if (StringUtils.isEmpty(importDto.getMaximumRetailPriceStr())) {
                lineValidateMsgList.add("最高零售价必填");
            }
            BigDecimal maximumRetailPrice;
            try {
                maximumRetailPrice = new BigDecimal(importDto.getMaximumRetailPriceStr());
                importDto.setMaximumRetailPrice(maximumRetailPrice);
            } catch (Exception e) {
                lineValidateMsgList.add("最高零售价应为数值类型");
            }
            if (!lineValidateMsgList.isEmpty()) {
                fieldValidateMsgList
                    .add("■ 第" + importDto.getLineNumber() + "行：" + String.join("，", lineValidateMsgList) + "；");
            }
        }
        if (!fieldValidateMsgList.isEmpty()) {
            return R.fail("导入失败！器材信息填写有误：" + String.join(" ", fieldValidateMsgList));
        }
        // 重复校验（文件行重复）
        List<String> lineRepeatedValidateMsgList = new ArrayList<>();
        List<List<DeviceImportDto>> importDtoGroupList = new ArrayList<>(importDtoList.stream()
            .collect(Collectors.groupingBy(e -> e.getName() + e.getManufacturerText() + e.getSize())).values());
        for (List<DeviceImportDto> importDtoGroup : importDtoGroupList) {
            if (importDtoGroup.size() > 1) {
                lineRepeatedValidateMsgList.add(
                    "■ 第" + importDtoGroup.stream().map(DeviceImportDto::getLineNumber).sorted().map(Object::toString)
                        .collect(Collectors.joining(",")) + "行的【" + importDtoGroup.get(0).getName() + "】重复；");
            }
        }
        if (!lineRepeatedValidateMsgList.isEmpty()) {
            return R.fail("导入失败！文件中存在重复器材：" + String.join(" ", lineRepeatedValidateMsgList));
        }
        // 重复校验（文件与数据库重复）
        List<String> dbRepeatedValidateMsgList = new ArrayList<>();
        for (DeviceImportDto importDto : importDtoList) {
            List<DeviceDefinition> deviceDefinitionList = deviceDefinitionService
                .list(new LambdaQueryWrapper<DeviceDefinition>().eq(DeviceDefinition::getName, importDto.getName())
                    .eq(DeviceDefinition::getManufacturerText, importDto.getManufacturerText())
                    .eq(DeviceDefinition::getSize, importDto.getSize()));
            if (!deviceDefinitionList.isEmpty()) {
                dbRepeatedValidateMsgList
                    .add("■ 第" + importDto.getLineNumber() + "行的【" + importDto.getName() + "】在系统中已存在；");
            }
        }
        if (!dbRepeatedValidateMsgList.isEmpty()) {
            return R.fail("导入失败！系统中存在重复器材：" + String.join(" ", dbRepeatedValidateMsgList));
        }
        return R.ok();
    }

    /**
     * 创建器材定义实体
     *
     * @param importDto 器材目录导入Dto
     * @param orgId 机构ID
     * @param defaultLocationId 默认位置ID
     * @param locationNameMap 位置名称匹配分组Map
     * @return 器材定义实体
     */
    private DeviceDefinition createDeviceDefinitionEntity(DeviceImportDto importDto, Long orgId, Long defaultLocationId,
        Map<String, List<Location>> locationNameMap) {
        DeviceDefinition deviceDefinition = new DeviceDefinition();
        // 根据输入的所在位置名称获取位置ID
        List<Location> mapLocationList = locationNameMap.get(importDto.getLocationName());
        if (mapLocationList == null || mapLocationList.isEmpty()) {
            deviceDefinition.setLocationId(defaultLocationId);
        } else {
            deviceDefinition.setLocationId(mapLocationList.get(0).getId());
        }
        deviceDefinition.setBusNo(assignSeqUtil.getSeq(AssignSeqEnum.DEVICE_NUM.getPrefix(), 10))
            .setName(importDto.getName()).setPyStr(ChineseConvertUtils.toPinyinFirstLetter(importDto.getName()))
            .setWbStr(ChineseConvertUtils.toWBFirstLetter(importDto.getName()))
            .setCategoryCode(importDto.getCategoryCode()).setTypeCode(importDto.getTypeCode())
            .setUnitCode(importDto.getUnitCode()).setSize(importDto.getSize())
            .setItemMinQuantity(importDto.getItemMinQuantity()).setItemMaxQuantity(importDto.getItemMaxQuantity())
            .setPartPercent(importDto.getPartPercent()).setMinUnitCode(importDto.getMinUnitCode()).setOrgId(orgId)
            .setHvcmFlag(CommonUtil.tryParseInt(importDto.getHvcmFlag())).setSalesUnitCode(importDto.getSalesUnitCode())
            .setApprovalNumber(importDto.getApprovalNumber()).setYbFlag(CommonUtil.tryParseInt(importDto.getYbFlag()))
            .setYbNo(importDto.getYbNo()).setYbOrgNo(importDto.getYbOrgNo())
            .setYbMatchFlag(CommonUtil.tryParseInt(importDto.getYbMatchFlag()))
            .setChrgitmLv(CommonUtil.tryParseInt(importDto.getChrgitmLv()))
            .setStatusEnum(PublicationStatus.ACTIVE.getValue()).setManufacturerText(importDto.getManufacturerText())
            .setAllergenFlag(CommonUtil.tryParseInt(importDto.getAllergenFlag()))
            .setRxFlag(CommonUtil.tryParseInt(importDto.getRxFlag()));
        return deviceDefinition;
    }

}
