package com.openhis.web.pharmacymanage.appservice.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

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

import com.core.common.core.domain.entity.SysDictData;
import com.core.common.utils.poi.ExcelUtil;
import com.core.system.mapper.SysDictDataMapper;
import com.core.system.service.ISysDictTypeService;
import com.openhis.web.reportmanage.utils.ExcelFillerUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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.exception.ServiceException;
import com.core.common.utils.*;
import com.openhis.administration.domain.Organization;
import com.openhis.administration.domain.TraceNoManage;
import com.openhis.administration.service.ILocationService;
import com.openhis.administration.service.IOrganizationService;
import com.openhis.administration.service.IPractitionerService;
import com.openhis.administration.service.ITraceNoManageService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.enums.ybenums.YbInvChgType;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.medication.domain.MedicationDefinition;
import com.openhis.medication.domain.MedicationDispense;
import com.openhis.medication.service.IMedicationDefinitionService;
import com.openhis.medication.service.IMedicationDispenseService;
import com.openhis.medication.service.impl.MedicationRequestServiceImpl;
import com.openhis.web.basedatamanage.appservice.IPractitionerAppService;
import com.openhis.web.basedatamanage.dto.PractitionerOrgAndLocationDto;
import com.openhis.web.basedatamanage.dto.UserAndPractitionerDto;
import com.openhis.web.inhospitalnursestation.appservice.IMedicineSummaryAppService;
import com.openhis.web.inhospitalnursestation.dto.AdmissionPageParam;
import com.openhis.web.inhospitalnursestation.dto.AdmissionPatientPageDto;
import com.openhis.web.inhospitalnursestation.mapper.AdviceProcessAppMapper;
import com.openhis.web.inventorymanage.appservice.impl.ReceiptApprovalAppServiceImpl;
import com.openhis.web.inventorymanage.dto.SupplyItemDetailDto;
import com.openhis.web.pharmacymanage.appservice.ISummaryDispenseMedicineAppService;
import com.openhis.web.pharmacymanage.dto.*;
import com.openhis.web.pharmacymanage.mapper.ReturnMedicineMapper;
import com.openhis.web.pharmacymanage.mapper.SummaryDispenseMedicineMapper;
import com.openhis.web.pharmacymanage.mapper.WesternMedicineDispenseMapper;
import com.openhis.workflow.domain.InventoryItem;
import com.openhis.workflow.domain.SupplyDelivery;
import com.openhis.workflow.domain.SupplyRequest;
import com.openhis.workflow.service.IDeviceDispenseService;
import com.openhis.workflow.service.IInventoryItemService;
import com.openhis.workflow.service.ISupplyDeliveryService;
import com.openhis.workflow.service.ISupplyRequestService;

/**
 * 住院汇总发放 应用实现类
 *
 * @author yuxj
 * @date 2025/6/3
 */
@Service
public class SummaryDispenseMedicineAppServiceImpl implements ISummaryDispenseMedicineAppService {

    @Resource
    private IPractitionerAppService practitionerAppService;

    @Resource
    private IMedicationDispenseService medicationDispenseService;

    @Resource
    private IDeviceDispenseService deviceDispenseService;

    @Resource
    private IInventoryItemService iInventoryItemService;

    @Resource
    private SummaryDispenseMedicineMapper inpatientMedicineDispenseMapper;

    @Resource
    private ReturnMedicineMapper returnMedicineMapper;

    @Autowired
    private ILocationService locationService;

    @Resource
    private IPractitionerService practitionerService;

    @Resource
    private ISupplyRequestService supplyRequestService;

    @Resource
    private ISupplyDeliveryService supplyDeliveryService;

    @Resource
    private ITraceNoManageService traceNoManageService;

    @Resource
    private WesternMedicineDispenseAppServiceImpl westernMedicineDispenseAppServiceImpl;

    @Resource
    private IMedicineSummaryAppService inpatientMedicineCollectionAppService;

    @Resource
    private WesternMedicineDispenseMapper westernMedicineDispenseMapper;

    @Resource
    private IOrganizationService organizationService;

    @Resource
    private AdviceProcessAppMapper adviceProcessAppMapper;

    @Resource
    private IInventoryItemService inventoryItemService;

    @Resource
    private IMedicationDefinitionService medicationDefinitionService;

    @Resource
    private ReceiptApprovalAppServiceImpl receiptApprovalAppService;

    @Resource
    private WesternMedicineDispenseAppServiceImpl westernMedicineDispenseAppService;

    @Resource
    private MedicationRequestServiceImpl medicationRequestService;

    @Resource
    private AssignSeqUtil assignSeqUtil;

    @Resource
    private ReturnMedicineAppServiceImpl returnMedicineAppService;
    private HttpServletResponse response;
    @Autowired
    private ISysDictTypeService sysDictTypeService;

    /**
     * 获取页面初始化信息
     *
     * @return 初始化信息
     */
    @Override
    public R<?> init() {

        DispenseInitDto initDto = new DispenseInitDto();

        // 获取科室下拉选列表
        List<Organization> organizationList =
                organizationService.getList(OrganizationType.DEPARTMENT.getValue(), OrganizationClass.CLINIC.getValue());
        List<DispenseInitDto.DepartmentOption> organizationOptions = organizationList.stream()
                .map(organization -> new DispenseInitDto.DepartmentOption(organization.getId(), organization.getName()))
                .collect(Collectors.toList());

        initDto.setDepartmentOptions(organizationOptions);
        return R.ok(initDto);
    }

    @Override
    public R<?> getEncounterInfoListPage(AdmissionPageParam admissionPageParam, String startTime, String endTime,
        Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
        // 构建查询条件
        QueryWrapper<AdmissionPageParam> queryWrapper = HisQueryUtils.buildQueryWrapper(admissionPageParam, searchKey,
            new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientWbStr, CommonConstants.FieldName.PatientPyStr,
                CommonConstants.FieldName.PatientName, CommonConstants.FieldName.BusNo)),
            request);
        // 入院患者分页列表
        Page<AdmissionPatientPageDto> admissionPatientPage =
            adviceProcessAppMapper.selectInpatientPage(new Page<>(pageNo, pageSize), queryWrapper,
                EncounterClass.IMP.getValue(), EncounterZyStatus.TO_BE_REGISTERED.getValue(),
                EncounterZyStatus.REGISTERED.getValue(), EncounterActivityStatus.ACTIVE.getValue(),
                LocationForm.WARD.getValue(), LocationForm.HOUSE.getValue(), LocationForm.BED.getValue());
        admissionPatientPage.getRecords().forEach(e -> {
            // 性别枚举
            e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum()));
            // 病情
            e.setPriorityEnum_enumText(EnumUtils.getInfoByValue(PriorityLevel.class, e.getPriorityEnum()));
            // 计算年龄
            if (e.getBirthDate() != null) {
                e.setAge(AgeCalculatorUtil.getAge(e.getBirthDate()));
            }
            // 住院状态
            e.setEncounterStatus_enumText(EnumUtils.getInfoByValue(EncounterZyStatus.class, e.getEncounterStatus()));
        });
        return R.ok(admissionPatientPage);
    }

    /**
     * 住院汇总药品
     *
     * @param searchParam 查询信息
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 药品汇总
     */
    @Override
    public R<?> getSummaryMedicationInfo(MedicineSummarySearchParam searchParam, Integer pageNo, Integer pageSize) {
        ItemDispenseOrderDto itemDispenseOrderDto = new ItemDispenseOrderDto();
        itemDispenseOrderDto.setEncounterId(searchParam.getEncounterId());
        // 发药状态初始化
        Integer dispenseStatus = itemDispenseOrderDto.getStatusEnum();
        itemDispenseOrderDto.setStatusEnum(null);
        // 构建查询条件
        QueryWrapper<ItemDispenseOrderDto> queryWrapper =
            HisQueryUtils.buildQueryWrapper(itemDispenseOrderDto, null, null, null);
        // 处方单信息查询
        Page<ItemDispenseOrderDto> medicineDispenseOrderPage =
            westernMedicineDispenseMapper.selectMedicineDispenseOrderPage(new Page<>(pageNo, pageSize), queryWrapper,
                DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
                DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue(), dispenseStatus);
        medicineDispenseOrderPage.getRecords().forEach(medicineDispenseOrder -> {
            // 发药状态
            medicineDispenseOrder.setStatusEnum_enumText(
                EnumUtils.getInfoByValue(DispenseStatus.class, medicineDispenseOrder.getStatusEnum()));
            // 设置所在表名
            medicineDispenseOrder.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION);
        });
        return R.ok(medicineDispenseOrderPage);
    }


    /**
     * 导出住院发药信息到Excel
     *
     * @param searchParam 查询参数
     * @param searchKey 搜索关键字
     * @param pageNo 页码
     * @param pageSize 每页大小
     * @param request HTTP请求对象
     * @param response HTTP响应对象
     */
    @Override
    public void makeExcelFile(MedicineSummarySearchParam searchParam, Integer pageNo,
                              Integer pageSize, String searchKey,
                              HttpServletRequest request, HttpServletResponse response) {

        // 获取发药数据
        R<?> result = this.getSummaryMedicationInfo(searchParam,1, 10000);

        if (result != null && result.getCode() == 200 && result.getData() != null) {
            // 获取Page对象中的记录列表
            Page<ItemDispenseOrderDto> pageData = (Page<ItemDispenseOrderDto>) result.getData();
            List<ItemDispenseOrderDto> dataList = pageData.getRecords();
                try {
                    //获取药品类型
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        String itemType = itemDispenseOrderDto.getItemType();
                        if (itemType != null) {
                            List<SysDictData> itemTypeList = sysDictTypeService.selectDictDataByType("med_category_code");
                            if (itemTypeList != null) {
                                for (SysDictData dictData : itemTypeList) {
                                    if (dictData != null && dictData.getDictValue() != null
                                            && dictData.getDictValue().equals(itemType)) {
                                        itemDispenseOrderDto.setItemType_dictText(dictData.getDictLabel());
                                        break;
                                    }

                                }
                            }
                        }
                    }


                    //用药频次
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        String rateCode = itemDispenseOrderDto.getRateCode();
                        if (rateCode != null) {
                            List<SysDictData> rateCodeList = sysDictTypeService.selectDictDataByType("rate_code");
                            if (rateCodeList != null) {
                                for (SysDictData dictData : rateCodeList) {
                                    if (dictData != null && dictData.getDictValue() != null
                                            && dictData.getDictValue().equals(rateCode)) {
                                        itemDispenseOrderDto.setRateCode_dictText(dictData.getDictLabel());
                                        break;
                                    }

                                }
                            }
                        }
                    }


                    //用法
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        String methodCode = itemDispenseOrderDto.getMethodCode();
                        if (methodCode != null) {
                            List<SysDictData> methodCodeList = sysDictTypeService.selectDictDataByType("method_code");
                            if (methodCodeList != null) {
                                for (SysDictData dictData : methodCodeList) {
                                    if (dictData != null && dictData.getDictValue() != null
                                            && dictData.getDictValue().equals(methodCode)) {
                                        itemDispenseOrderDto.setMethodCode_dictText(dictData.getDictLabel());
                                        break;
                                    }

                                }
                            }
                        }
                    }


                    // 计量单位
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        //获取计量单位翻译前的值
                        String doseUnitCode = itemDispenseOrderDto.getDoseUnitCode();
                        if (doseUnitCode != null) {
                            //从系统字典服务中查询计量单位的值
                            List<SysDictData> doseUnitCodeList = sysDictTypeService.selectDictDataByType("unit_code");
                            if (doseUnitCodeList != null) {
                                for (SysDictData dictData : doseUnitCodeList) {
                                    if (dictData != null && dictData.getDictValue() != null
                                            && dictData.getDictValue().equals(doseUnitCode)) {
                                        itemDispenseOrderDto.setDoseUnitCode_dictText(dictData.getDictLabel());
                                        break;
                                    }
                                }
                            }
                        }
                    }


                    // 获取单位翻译值
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        //获取单位翻译前的值
                        String unitCode = itemDispenseOrderDto.getUnitCode();
                        if (unitCode != null) {
                            //从系统字典服务中查询单位的值
                            List<SysDictData> unitCodeList = sysDictTypeService.selectDictDataByType("unit_code");
                            if (unitCodeList != null) {
                                for (SysDictData dictData : unitCodeList) {
                                    if (dictData != null && dictData.getDictValue() != null
                                            && dictData.getDictValue().equals(unitCode)) {
                                        itemDispenseOrderDto.setUnitCode_dictText(dictData.getDictLabel());
                                        break;
                                    }
                                }
                            }
                        }
                    }


                    // 金额保留两位小数
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        //获取金额的值
                        BigDecimal totalPrice = itemDispenseOrderDto.getTotalPrice();
                        //把金额值转换成double
                        double doubleValue = totalPrice.doubleValue();
                        double value = Math.round(doubleValue * 100.0) / 100.0;
                        itemDispenseOrderDto.setTotalPrice(BigDecimal.valueOf(value));
                    }

                    // 单价保留两位小数
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        //获取单价的值
                        BigDecimal unitPrice = itemDispenseOrderDto.getUnitPrice();
                        //把单价值转换成double
                        double valueLis = unitPrice.doubleValue();
                        double valuePis = Math.round(valueLis * 100.0) / 100.0;
                        itemDispenseOrderDto.setUnitPrice(BigDecimal.valueOf(valuePis));
                    }

                    //单次剂量保留两位小数
                    for (ItemDispenseOrderDto itemDispenseOrderDto : dataList) {
                        //获取单次剂量的值
                        BigDecimal dose = itemDispenseOrderDto.getDose();
                        //把单次剂量转换成double
                        double valuePas = dose.doubleValue();
                        double valueRas = Math.round(valuePas * 100.0) / 100.0;
                        itemDispenseOrderDto.setDose(BigDecimal.valueOf(valueRas));
                    }

                ExcelUtil<ItemDispenseOrderDto> util = new ExcelUtil<ItemDispenseOrderDto>(ItemDispenseOrderDto.class);
                 util.exportExcel(response, dataList, "住院发药单");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.printf("导出住院发药Excel失败：%s", e.getMessage());
            }
        }
    }


    /**
     * 住院汇总发药单
     *
     * @param searchParam 查询信息
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param request 请求数据
     * @return 药品汇总
     */
    @Override
    public R<?> getSummaryFromInfo(FromSummarySearchParam searchParam, String startTime, String endTime,
        String searchKey, Integer pageNo, Integer pageSize, HttpServletRequest request) {
        // 构建查询条件
        QueryWrapper<MedicineSummarySearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(searchParam, searchKey,
            new HashSet<>(List.of(CommonConstants.FieldName.ApplicantName, CommonConstants.FieldName.BusNo)), request);

        // 查询医嘱详细信息
        Page<MedicineSummaryDto> prescriptionItemInfoPageDto =
            inpatientMedicineDispenseMapper.selectMedicationSummaryInfo(new Page<>(pageNo, pageSize), queryWrapper);

        List<MedicineSummaryDto> medicineSummaryDtoList = prescriptionItemInfoPageDto.getRecords();

        List<MedicineSummaryDto.Option> unitList;
        // 个别项目设定
        for (MedicineSummaryDto prescriptionInfoDto : medicineSummaryDtoList) {
            // 状态
            prescriptionInfoDto.setStatusEnum_enumText(
                EnumUtils.getInfoByValue(DispenseStatus.class, prescriptionInfoDto.getStatusEnum()));
            // 追溯码单位列表
            unitList = new ArrayList<>();
            unitList.add(new MedicineSummaryDto.Option(prescriptionInfoDto.getMaxUnitCode(),
                prescriptionInfoDto.getMaxUnitCode_dictText()));
            unitList.add(new MedicineSummaryDto.Option(prescriptionInfoDto.getMinUnitCode(),
                prescriptionInfoDto.getMinUnitCode_dictText()));

            prescriptionInfoDto.setUnitList(unitList);
        }

        // 获取当前用户id
        Long userId = SecurityUtils.getUserId();
        UserAndPractitionerDto userAndPractitionerDto = new UserAndPractitionerDto();
        userAndPractitionerDto.setUserId(userId);
        IPage<UserAndPractitionerDto> userPractitionerPage =
            practitionerAppService.getUserPractitionerPage(userAndPractitionerDto, "", 1, 1);
        // 查询该用户管理的药房
        List<Long> locationIdList = userPractitionerPage.getRecords().get(0).getManageMedicationLocationDtoList()
            .stream().map(PractitionerOrgAndLocationDto::getLocationId).toList();

        List<FromSummaryDto> fromSummaryDtoList = new ArrayList<>();
        for (MedicineSummaryDto medicineSummaryDto : medicineSummaryDtoList) {

            FromSummaryDto fromSummaryDto = new FromSummaryDto();
            BeanUtils.copyProperties(medicineSummaryDto, fromSummaryDto);

            if (!locationIdList.isEmpty() && locationIdList.contains(fromSummaryDto.getSourceLocationId()))
                fromSummaryDtoList.add(fromSummaryDto);
        }

        return R.ok(fromSummaryDtoList);
    }

    /**
     * 住院药品汇总发药单详细
     *
     * @param searchParam 查询条件
     * @param searchKey 模糊查询关键字
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param request 请求数据
     */
    @Override
    public R<?> getOrderInfo(FromSearchParam searchParam, String searchKey, Integer pageNo, Integer pageSize,
        HttpServletRequest request) {

        // 构建查询条件
        QueryWrapper<FromSearchParam> queryWrapper =
            HisQueryUtils.buildQueryWrapper(searchParam, searchKey, null, request);

        // 查询医嘱详细信息
        Page<MedicineSummaryDto> prescriptionItemInfoPageDto =
            inpatientMedicineDispenseMapper.selectOrderInfo(new Page<>(pageNo, pageSize), queryWrapper);

        List<MedicineSummaryDto.Option> unitList;
        // 个别项目设定
        for (MedicineSummaryDto prescriptionInfoDto : prescriptionItemInfoPageDto.getRecords()) {
            // 状态
            prescriptionInfoDto.setStatusEnum_enumText(
                EnumUtils.getInfoByValue(DispenseStatus.class, prescriptionInfoDto.getStatusEnum()));
            // 追溯码单位列表
            unitList = new ArrayList<>();
            unitList.add(new MedicineSummaryDto.Option(prescriptionInfoDto.getMaxUnitCode(),
                prescriptionInfoDto.getMaxUnitCode_dictText()));
            unitList.add(new MedicineSummaryDto.Option(prescriptionInfoDto.getMinUnitCode(),
                prescriptionInfoDto.getMinUnitCode_dictText()));

            prescriptionInfoDto.setUnitList(unitList);
        }
        return R.ok(prescriptionItemInfoPageDto);
    }

    /**
     * 处方单核对发药
     *
     * @param dispenseMedicineList 发药信息
     * @return 处理结果
     */
    @Override
    public R<?> SummaryDispenseMedicine(List<DispenseItemDto> dispenseMedicineList) {
        // 汇总状态更新标志
        boolean summaryFlag = false;
        List<InventoryItem> inventoryItemList = new ArrayList<>();

        // 获取发药单id列表
        List<Long> medDispenseIdList =
            dispenseMedicineList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());

        if (medDispenseIdList.stream().allMatch(Objects::isNull)) {
            List<String> busNoList =
                dispenseMedicineList.stream().map(DispenseItemDto::getBusNo).collect(Collectors.toList());
            medDispenseIdList = medicationDispenseService.getMedDispenseBySummaryNo(busNoList).stream()
                .map(MedicationDispense::getId).toList();
            summaryFlag = true;
        }

        // 获取库存信息
        List<UnDispenseInventoryDto> inventoryList =
            returnMedicineMapper.selectInventoryInfoList(null, medDispenseIdList,
                CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION);

        // 按每个药品分组
        Map<Long, List<UnDispenseInventoryDto>> groupedByItemId =
            inventoryList.stream().collect(Collectors.groupingBy(UnDispenseInventoryDto::getItemId));
        // 遍历每个分组校验库存状态
        for (Map.Entry<Long, List<UnDispenseInventoryDto>> entry : groupedByItemId.entrySet()) {
            List<UnDispenseInventoryDto> groupItems = entry.getValue();
            if (groupItems.stream().map(UnDispenseInventoryDto::getInventoryStatusEnum)
                .allMatch(x -> x.equals(PublicationStatus.RETIRED.getValue()))) {
                // 库存停供校验
                return R.fail(groupItems.get(0).getItemName() + "库存已停供");
            }
        }
        if (!inventoryList.isEmpty()) {
            for (UnDispenseInventoryDto unDispenseInventoryDto : inventoryList) {
                if (PublicationStatus.ACTIVE.getValue().equals(unDispenseInventoryDto.getInventoryStatusEnum())) {
                    InventoryItem inventoryItem = new InventoryItem();
                    // 库存数量判定
                    if (unDispenseInventoryDto.getDispenseUnit()
                        .equals(unDispenseInventoryDto.getInventoryUnitCode())) {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-请求数量
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity()
                            .subtract(unDispenseInventoryDto.getQuantity());
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        } else {
                            inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                        }
                    } else {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-拆零数量（拆零比×请求数量）
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity().subtract(
                            unDispenseInventoryDto.getPartPercent().multiply(unDispenseInventoryDto.getQuantity()));
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        } else {
                            inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                        }
                    }
                    inventoryItemList.add(inventoryItem);
                }
            }
        }
        // 药品发药信息查询
        List<MedicationDispense> dispenseList = medicationDispenseService
            .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
        // 追溯码列表
        List<TraceNoManage> tracesNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;
        List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
        if (dispenseList != null) {
            // if (dispenseList.stream().map(MedicationDispense::getStatusEnum)
            // .anyMatch(x -> !x.equals(DispenseStatus.PREPARED.getValue()))) {
            // throw new ServiceException("发药失败，请检查发药单状态");
            // } else {
            for (MedicationDispense medicationDispense : dispenseList) {
                // 药品发放状态
                medicationDispense.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                // 状态变更时间
                medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
                // 发药数量
                medicationDispense.setDispenseQuantity(medicationDispense.getQuantity());
                // 发药时间
                medicationDispense.setDispenseTime(DateUtils.getNowDate());
                // 发药人
                medicationDispense.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
                // 设置库存变更参数
                supplyItemDetailList.add(new SupplyItemDetailDto().setItemId(medicationDispense.getMedicationId())
                    .setLotNumber(medicationDispense.getLotNumber())
                    .setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION));
                // 使用逗号分割追溯码并转换为List
                if (medicationDispense.getTraceNo() != null) {
                    String[] traceNoList = medicationDispense.getTraceNo().split(CommonConstants.Common.COMMA);
                    for (String item : traceNoList) {
                        traceNoManage = new TraceNoManage();
                        // 追溯码处理
                        traceNoManage.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
                            // 项目id
                            .setItemId(medicationDispense.getMedicationId())
                            // 仓库类型
                            .setLocationTypeEnum(LocationForm.PHARMACY.getValue())
                            // 仓库
                            .setLocationId(medicationDispense.getLocationId())
                            // 产品批号
                            .setLotNumber(medicationDispense.getLotNumber())
                            // 追溯码
                            .setTraceNo(item)
                            // 追溯码状态
                            .setStatusEnum(TraceNoStatus.OUT.getValue())
                            // 追溯码单位
                            .setUnitCode(medicationDispense.getUnitCode())
                            // 操作类型
                            .setOperationType(SupplyType.DISPENSE_MEDICATION.getValue());
                        tracesNoManageList.add(traceNoManage);
                    }
                }
            }
            // 药品发放更新
            medicationDispenseService.updateBatchById(dispenseList);
            // 汇总发放更新
            if (summaryFlag) {
                List<Long> requestId = supplyRequestService.getSupplyByBusNo(dispenseMedicineList.get(0).getBusNo())
                    .stream().map(SupplyRequest::getId).collect(Collectors.toList());
                List<SupplyDelivery> supplyDeliveryList = supplyDeliveryService.selectByRequestIdList(requestId);
                for (SupplyDelivery supplyDelivery : supplyDeliveryList) {
                    // 药品发放状态
                    supplyDelivery.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                    // 发药时间
                    supplyDelivery.setOccurrenceTime(DateUtils.getNowDate());
                    // 发药人
                    supplyDelivery.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
                }
                supplyDeliveryService.updateBatchById(supplyDeliveryList);
                List<SupplyRequest> supplyRequestList = supplyRequestService.selectByIdList(requestId);
                for (SupplyRequest supplyRequest : supplyRequestList) {
                    supplyRequest.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                }
                supplyRequestService.updateBatchById(supplyRequestList);
            }
            // }
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        // 库存更新
        inventoryItemService.updateBatchById(inventoryItemList);
        // 追溯码管理表数据追加
        traceNoManageService.saveBatch(tracesNoManageList);
        // 返回信息
        String returnMsg = null;
        List<String> uploadFailedNoList;
        // 调用医保商品销售接口
        String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
        if (Whether.YES.getCode().equals(ybSwitch)) {
            // 设置进销存参数
            List<MedicationDefinition> medicationDefinitions = medicationDefinitionService.listByIds(
                supplyItemDetailList.stream().map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            // 用itemId分组
            Map<Long, MedicationDefinition> medicationMap = medicationDefinitions.stream()
                .collect(Collectors.toMap(MedicationDefinition::getId, Function.identity()));
            // 设置库存变更参数
            for (SupplyItemDetailDto dto : supplyItemDetailList) {
                if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dto.getItemTable())) {
                    MedicationDefinition med = medicationMap.get(dto.getItemId());
                    if (med != null) {
                        dto.setItemBusNo(med.getBusNo()).setPartPercent(med.getPartPercent()).setRxFlag(med.getRxFlag())
                            .setYbNo(med.getYbNo());
                    }
                }
            }
            uploadFailedNoList = westernMedicineDispenseAppService.ybMedicineIntegrated(medDispenseIdList, null);
            uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
                YbInvChgType.OTHER_OUT, DateUtils.getNowDate());
            if (uploadFailedNoList != null) {
                returnMsg = "3505商品销售上传错误，错误项目编码" + uploadFailedNoList;
            } else {
                returnMsg = "3505商品销售上传成功";
            }
        }
        return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 作废
     *
     * @param dispenseMedicineList 作废信息
     * @return 处理结果
     */
    @Override
    public R<?> dispenseCancel(List<DispenseItemDto> dispenseMedicineList) {
        // 汇总状态更新标志
        boolean summaryFlag = false;
        // 获取发药单id列表
        List<Long> medDispenseIdList =
            dispenseMedicineList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());

        if (medDispenseIdList.isEmpty()) {
            List<String> busNoList =
                dispenseMedicineList.stream().map(DispenseItemDto::getBusNo).collect(Collectors.toList());
            medDispenseIdList = medicationDispenseService.getMedDispenseBySummaryNo(busNoList).stream()
                .map(MedicationDispense::getId).toList();
            summaryFlag = true;
        }

        // 药品发药信息查询
        List<MedicationDispense> dispenseList = medicationDispenseService
            .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
        if (dispenseList != null) {
            for (MedicationDispense medicationDispense : dispenseList) {
                // 药品发放状态
                medicationDispense.setStatusEnum(DispenseStatus.DECLINED.getValue());
                // 未发药原因
                medicationDispense.setNotPerformedReasonEnum(dispenseMedicineList.get(0).getNotPerformedReasonEnum());
                // 状态变更时间
                medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
            }
            // 药品发放更新
            medicationDispenseService.updateBatchById(dispenseList);
            // 汇总发放更新
            if (summaryFlag) {
                List<Long> requestId = supplyRequestService.getSupplyByBusNo(dispenseMedicineList.get(0).getBusNo())
                    .stream().map(SupplyRequest::getId).collect(Collectors.toList());
                List<SupplyDelivery> supplyDeliveryList = supplyDeliveryService.selectByRequestIdList(requestId);
                for (SupplyDelivery supplyDelivery : supplyDeliveryList) {
                    // 药品发放状态
                    supplyDelivery.setStatusEnum(DispenseStatus.DECLINED.getValue());
                }
                supplyDeliveryService.updateBatchById(supplyDeliveryList);
            }
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        return R.ok(MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 退药处理
     *
     * @param dispenseMedicineList 退药清单
     * @return 处理结果
     */
    @Override
    public R<?> medicineReturn(List<DispenseItemDto> dispenseMedicineList) {
        if (dispenseMedicineList == null || dispenseMedicineList.isEmpty()) {
            return R.ok();
        }

        // 汇总状态更新标志
        boolean summaryFlag = false;
        // 获取发药单id列表
        List<Long> medDispenseIdList =
            dispenseMedicineList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());

        if (medDispenseIdList.stream().allMatch(Objects::isNull)) {
            List<String> busNoList =
                dispenseMedicineList.stream().map(DispenseItemDto::getBusNo).collect(Collectors.toList());
            medDispenseIdList = medicationDispenseService.getMedDispenseBySummaryNo(busNoList).stream()
                .map(MedicationDispense::getId).toList();
            summaryFlag = true;
        }

        // 退药请求列表
        List<ReturnMedicineDto> returnMedicineList = new ArrayList<>();
        // 追溯码列表
        List<TraceNoManage> traceNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;

        medDispenseIdList.forEach(dispenseId -> {
            MedicationDispense medicationDispense = medicationDispenseService.getById(dispenseId);
            returnMedicineList
                .add(new ReturnMedicineDto().setDispenseId(dispenseId).setRequestId(medicationDispense.getMedReqId()));
        });

        // 获取药品退药请求id列表
        List<Long> medRequestIdList =
            returnMedicineList.stream().map(ReturnMedicineDto::getRequestId).collect(Collectors.toList());

        if (!medRequestIdList.isEmpty()) {
            // 药品已退药信息查询
            List<MedicationDispense> refundList = medicationDispenseService.list(
                new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getMedReqId, medRequestIdList));
            if (refundList != null) {
                if (refundList.stream().map(MedicationDispense::getStatusEnum)
                    .anyMatch(x -> x.equals(DispenseStatus.REFUNDED.getValue()))) {
                    throw new ServiceException("药品已退药，请勿重复退药");
                }
            }
        }

        // 退药单列表
        List<MedicationDispense> medicationRefundList = new ArrayList<>();
        List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
        if (!medDispenseIdList.isEmpty()) {
            // 药品已发放信息查询
            List<MedicationDispense> medicationDispenseList = medicationDispenseService
                .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
            // 根据发药单对应生成退药单
            for (MedicationDispense medicationDispense : medicationDispenseList) {
                // 退药的药品请求id
                for (ReturnMedicineDto returnMedicineDto : returnMedicineList) {
                    if (returnMedicineDto.getDispenseId().equals(medicationDispense.getId())) {
                        medicationDispense.setMedReqId(returnMedicineDto.getRequestId());
                    }
                }
                // 药品发放编码
                medicationDispense.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_DIS_NO.getPrefix(), 4));
                // 退药状态
                medicationDispense.setStatusEnum(DispenseStatus.REFUNDED.getValue());
                // 状态变更时间
                medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
                // 退药时间
                medicationDispense.setDispenseTime(DateUtils.getNowDate());
                // 退药人
                medicationDispense.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
                medicationDispense.setId(null);
                medicationRefundList.add(medicationDispense);
                // 设置库存变更参数
                supplyItemDetailList.add(new SupplyItemDetailDto()
                    .setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
                    .setItemId(medicationDispense.getMedicationId()).setLotNumber(medicationDispense.getLotNumber()));
                if (medicationDispense.getTraceNo() != null) {
                    // 使用逗号分割追溯码并转换为List
                    String[] traceNoList = medicationDispense.getTraceNo().split(CommonConstants.Common.COMMA);
                    for (String item : traceNoList) {
                        traceNoManage = new TraceNoManage();
                        // 追溯码处理
                        traceNoManage.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
                            // 项目id
                            .setItemId(medicationDispense.getMedicationId())
                            // 仓库类型
                            .setLocationTypeEnum(null)
                            // 仓库
                            .setLocationId(medicationDispense.getLocationId())
                            // 仓位
                            .setLocationStoreId(null)
                            // 产品批号
                            .setLotNumber(medicationDispense.getLotNumber())
                            // 追溯码
                            .setTraceNo(item)
                            // 追溯码状态
                            .setStatusEnum(TraceNoStatus.IN.getValue())
                            // 追溯码单位
                            .setUnitCode(medicationDispense.getUnitCode())
                            // 操作类型
                            .setOperationType(SupplyType.RETURN_MEDICATION.getValue());
                        traceNoManageList.add(traceNoManage);
                    }
                }
            }
            medicationDispenseService.saveBatch(medicationRefundList);
            // 药品退药请求状态变更(待退药→已完成)
            medicationRequestService.updateCompletedStatusBatch(medRequestIdList, null, null);
            // 汇总退药更新
            if (summaryFlag) {
                List<Long> requestId = supplyRequestService.getSupplyByBusNo(dispenseMedicineList.get(0).getBusNo())
                    .stream().map(SupplyRequest::getId).collect(Collectors.toList());
                List<SupplyDelivery> supplyDeliveryList = supplyDeliveryService.selectByRequestIdList(requestId);
                for (SupplyDelivery supplyDelivery : supplyDeliveryList) {
                    // 药品发放状态
                    supplyDelivery.setStatusEnum(DispenseStatus.REFUNDED.getValue());
                    // 发药时间
                    supplyDelivery.setOccurrenceTime(DateUtils.getNowDate());
                    // 发药人
                    supplyDelivery.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
                }
                supplyDeliveryService.updateBatchById(supplyDeliveryList);
                List<SupplyRequest> supplyRequestList = supplyRequestService.selectByIdList(requestId);
                for (SupplyRequest supplyRequest : supplyRequestList) {
                    supplyRequest.setStatusEnum(DispenseStatus.REFUNDED.getValue());
                }
                supplyRequestService.updateBatchById(supplyRequestList);
            }
        }

        List<InventoryItem> inventoryItemList = new ArrayList<>();
        // 获取库存信息
        List<UnDispenseInventoryDto> inventoryList =
            returnMedicineMapper.selectInventoryInfoList(null, medDispenseIdList,
                CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION);

        if (inventoryList != null && !inventoryList.isEmpty()) {
            // 设置库存数量
            for (UnDispenseInventoryDto inventory : inventoryList) {
                // 库存表项目设定
                InventoryItem inventoryItem = new InventoryItem();
                // id
                inventoryItem.setId(inventory.getInventoryId());
                // 库存数量
                if (inventory.getDispenseUnit().equals(inventory.getInventoryUnitCode())) {
                    // 当前库存数量(拆零单位)=当前库存数量(拆零单位)+待退数量
                    inventoryItem.setQuantity(inventory.getInventoryQuantity().add(inventory.getDispenseQuantity()));
                } else {
                    // 当前库存数量(拆零单位)=当前库存数量(拆零单位)+退药数量（拆零比×待退数量）
                    inventoryItem.setQuantity(inventory.getInventoryQuantity()
                        .add(inventory.getPartPercent().multiply(inventory.getDispenseQuantity())));
                }
                inventoryItemList.add(inventoryItem);
            }
            // 库存更新
            iInventoryItemService.updateBatchById(inventoryItemList);
            // 追溯码管理表数据追加
            traceNoManageService.saveBatch(traceNoManageList);
        }

        // 返回信息
        String returnMsg = null;
        List<String> uploadFailedNoList;
        // 调用医保商品销售退货接口
        String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
        if (Whether.YES.getCode().equals(ybSwitch)) {
            List<MedicationDefinition> medicationDefinitions = new ArrayList<>();
            if (!medicationRefundList.isEmpty()) {
                // 设置进销存参数
                medicationDefinitions = medicationDefinitionService.listByIds(supplyItemDetailList.stream()
                    .filter(x -> x.getItemTable().equals(CommonConstants.TableName.MED_MEDICATION_DEFINITION))
                    .map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            }

            // 创建映射表，添加空集合保护
            Map<Long, MedicationDefinition> medicationMap =
                medicationDefinitions != null ? medicationDefinitions.stream().filter(Objects::nonNull)
                    .collect(Collectors.toMap(MedicationDefinition::getId, Function.identity())) : new HashMap<>();

            // 设置库存变更参数，添加完整判空
            for (SupplyItemDetailDto dto : supplyItemDetailList) {
                if (dto == null)
                    continue;
                if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dto.getItemTable())) {
                    if (dto.getItemId() != null) {
                        MedicationDefinition med = medicationMap.get(dto.getItemId());
                        if (med != null) {
                            dto.setItemBusNo(med.getBusNo()).setPartPercent(med.getPartPercent())
                                .setRxFlag(med.getRxFlag()).setYbNo(med.getYbNo());
                        }
                    }
                }
            }
            uploadFailedNoList = returnMedicineAppService.ybReturnIntegrated(medDispenseIdList, null);
            uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
                YbInvChgType.OTHER_OUT, DateUtils.getNowDate());
            if (uploadFailedNoList != null) {
                returnMsg = "3506商品销售退货上传错误，错误项目编码" + uploadFailedNoList;
            } else {
                returnMsg = "3506商品销售退货上传成功";
            }
        }
        // 返回退药成功信息
        return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"退药"}));
    }

}
