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

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.openhis.administration.domain.Location;
import com.openhis.administration.domain.TraceNoManage;
import com.openhis.administration.mapper.TraceNoManageMapper;
import com.openhis.administration.service.ILocationService;
import com.openhis.administration.service.ITraceNoManageService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.ItemType;
import com.openhis.common.enums.SupplyType;
import com.openhis.common.enums.TraceNoStatus;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.web.inventorymanage.appservice.ITraceNoAppService;
import com.openhis.web.inventorymanage.dto.*;
import com.openhis.web.inventorymanage.mapper.TraceNoAppMapper;

/**
 * 追溯码管理 impl
 *
 * @author yuxj
 * @date 2025-07-07
 */
@Service
public class TraceNoAppServiceImpl implements ITraceNoAppService {
    @Autowired
    private ITraceNoManageService traceNoManageService;
    @Autowired
    private ILocationService locationService;
    @Resource
    private TraceNoAppMapper traceNoAppMapper;
    @Resource
    private TraceNoManageMapper traceNoManageMapper;

    /**
     * 追溯码管理页面初始化
     *
     * @return 初始化信息
     */
    @Override
    public R<?> traceNoInit() {

        TraceNoInitDto initDto = new TraceNoInitDto();

        // 药房,药库列表
        List<Location> locationList = locationService.getPharmacyCabinetList();
        // 药房，药库
        List<TraceNoInitDto.locationOption> locationOptions = locationList.stream()
            .map(location -> new TraceNoInitDto.locationOption(location.getId(), location.getName()))
            .collect(Collectors.toList());

        // 追溯码状态
        List<TraceNoInitDto.itemTypeOption> traceNoStatusOptions = Stream.of(TraceNoStatus.values())
            .map(itemType -> new TraceNoInitDto.itemTypeOption(itemType.getValue(), itemType.getInfo()))
            .collect(Collectors.toList());

        // 项目类型
        List<TraceNoInitDto.itemTypeOption> itemTypeOptions = Stream.of(ItemType.values())
            .map(itemType -> new TraceNoInitDto.itemTypeOption(itemType.getValue(), itemType.getInfo()))
            .collect(Collectors.toList());

        // 操作类型
        List<TraceNoInitDto.itemTypeOption> operationTypeOptions = Stream.of(SupplyType.values())
            .map(itemType -> new TraceNoInitDto.itemTypeOption(itemType.getValue(), itemType.getInfo()))
            .collect(Collectors.toList());

        initDto.setLocationOptions(locationOptions).setTraceNoStatusOptions(traceNoStatusOptions)
            .setItemTypeOptions(itemTypeOptions).setOperationTypeOptions(operationTypeOptions);

        return R.ok(initDto);
    }

    /**
     * 追溯码管理列表
     *
     * @param traceNoSearchParam 查询条件
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param searchKey 模糊查询关键字
     * @param request 请求数据
     * @return
     */
    @Override
    public R<?> getPage(TraceNoSearchParam traceNoSearchParam, Integer pageNo, Integer pageSize, String searchKey,
        HttpServletRequest request) {
        // 构建查询条件
        QueryWrapper<TraceNoSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(traceNoSearchParam, searchKey,
            new HashSet<>(Arrays.asList("name", "trace_no")), request);
        // 设置排序
        queryWrapper.orderByDesc("create_time");

        // 查询退货出库单据分页列表
        Page<TraceNoDetailsPageDto> traceNoDetailsPage =
            traceNoAppMapper.selectDetailsPage(new Page<>(pageNo, pageSize), queryWrapper);
        traceNoDetailsPage.getRecords().forEach(e -> {
            // 追溯码状态
            e.setStatusEnum_enumText(EnumUtils.getInfoByValue(TraceNoStatus.class, e.getStatusEnum()));
            // 操作类型
            e.setOperationType_enumText(EnumUtils.getInfoByValue(SupplyType.class, e.getOperationType()));
            // 项目类型
            e.setItemType_enumText(EnumUtils.getInfoByValue(ItemType.class, e.getItemType()));
        });

        return R.ok(traceNoDetailsPage);
    }

    /**
     * 添加追溯码信息
     *
     * @param traceNoInfoList 追溯码信息
     * @return 操作结果
     */
    @Override
    public R<?> addTraceNoInfo(List<TraceNoInfoParam> traceNoInfoList) {

        List<TraceNoManage> traceNoManageList = new ArrayList<>();
        for (TraceNoInfoParam item : traceNoInfoList) {
            // 初始化单据信息
            TraceNoManage traceNoManage = new TraceNoManage();
            // 生成待发送的退货出库单据
            traceNoManage
                // 项目所属表
                .setItemTable(item.getItemTable())
                // 项目id
                .setItemId(item.getItemId())
                // 仓库类型
                .setLocationTypeEnum(item.getLocationTypeEnum())
                // 仓库
                .setLocationId(item.getLocationId())
                // 仓位
                .setLocationStoreId(item.getLocationStoreId())
                // 产品批号
                .setLotNumber(item.getLotNumber())
                // 追溯码
                .setTraceNo(item.getTraceNo())
                // 追溯码状态
                .setStatusEnum(item.getStatusEnum())
                // 追溯码单位
                .setUnitCode(item.getUnitCode())
                // 操作类型
                .setOperationType(item.getOperationType());
            traceNoManageList.add(traceNoManage);
        }

        // 保存
        boolean flg = traceNoManageService.saveBatch(traceNoManageList);
        if (!flg) {
            return R.fail(PromptMsgConstant.Common.M00011);
        }
        // 返回请求id
        return R.ok(PromptMsgConstant.Common.M00004);
    }

    /**
     * 追加追溯码信息
     *
     * @param supplyItemDetailList 单据信息
     * @param statusEnum 追溯码状态
     * @param operationType 操作类型
     * @return 操作结果
     */
    @Override
    public boolean addTraceNoManage(List<SupplyItemDetailDto> supplyItemDetailList, Integer statusEnum,
        Integer operationType) {
        // 追溯码列表
        List<TraceNoManage> traceNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;
        for (SupplyItemDetailDto supplyItemDetailDto : supplyItemDetailList) {
            // 使用逗号分割追溯码并转换为List
            String[] traceNoList = Arrays.stream(supplyItemDetailDto.getTraceNo().split(CommonConstants.Common.COMMA))
                .filter(traceNo -> !traceNo.isEmpty()) // 过滤null和空字符串
                .toArray(String[]::new); // 转换回String数组

            for (String item : traceNoList) {
                traceNoManage = new TraceNoManage();
                // 追溯码处理
                traceNoManage.setItemTable(supplyItemDetailDto.getItemTable())
                    // 项目id
                    .setItemId(supplyItemDetailDto.getItemId())
                    // 产品批号
                    .setLotNumber(supplyItemDetailDto.getLotNumber())
                    // 追溯码
                    .setTraceNo(item)
                    // 追溯码状态
                    .setStatusEnum(statusEnum)
                    // 追溯码单位
                    .setUnitCode(supplyItemDetailDto.getTraceNoUnitCode())
                    // 操作类型
                    .setOperationType(operationType);
                // 追溯码[进]对应的是目的仓库，[出]对应源仓库
                if (TraceNoStatus.IN.getValue().equals(statusEnum)) {
                    if (supplyItemDetailDto.getPurposeTypeEnum() != null) {
                        traceNoManage.setLocationTypeEnum(supplyItemDetailDto.getPurposeTypeEnum());
                    }
                    if (supplyItemDetailDto.getPurposeLocationId() != null) {
                        traceNoManage.setLocationId(supplyItemDetailDto.getPurposeLocationId());
                    }
                    if (supplyItemDetailDto.getPurposeLocationStoreId() != null) {
                        traceNoManage.setLocationStoreId(supplyItemDetailDto.getPurposeLocationStoreId());
                    }
                } else {
                    if (supplyItemDetailDto.getSourceTypeEnum() != null) {
                        traceNoManage.setLocationTypeEnum(supplyItemDetailDto.getSourceTypeEnum());
                    }
                    if (supplyItemDetailDto.getSourceLocationId() != null) {
                        traceNoManage.setLocationId(supplyItemDetailDto.getSourceLocationId());
                    }
                    if (supplyItemDetailDto.getSourceLocationStoreId() != null) {
                        traceNoManage.setLocationStoreId(supplyItemDetailDto.getSourceLocationStoreId());
                    }
                }
                traceNoManageList.add(traceNoManage);
            }
        }
        return traceNoManageService.saveBatch(traceNoManageList);
    }

    /**
     * 修改追溯码信息
     *
     * @param supplyItemDetailList 单据信息
     * @param operationType 操作类型
     * @return 操作结果
     */
    @Override
    public boolean updateTraceNoList(List<SupplyItemDetailDto> supplyItemDetailList, Integer operationType) {
        // 追溯码列表
        List<TraceNoManage> traceNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;
        for (SupplyItemDetailDto supplyItemDetailDto : supplyItemDetailList) {
            // 查询该商品都有什么追溯码
            List<TraceNoManage> traceNoInfoItemList = traceNoManageMapper.getItemTraceNoInfo(
                supplyItemDetailDto.getItemTable(), supplyItemDetailDto.getItemId(),
                supplyItemDetailDto.getPurposeLocationId(), supplyItemDetailDto.getLotNumber());
            List<String> traceNoList = traceNoInfoItemList.stream()
                .map(TraceNoManage::getTraceNo)  // 提取traceNo
                .filter(traceNo -> traceNo != null && !traceNo.isEmpty())  // 过滤null和空字符串
                .toList();
            // 使用逗号分割追溯码并转换为List
            List<String> traceNoAddList = Arrays.stream(supplyItemDetailDto.getTraceNo().split(","))
                .filter(traceNo -> traceNo != null &&  !traceNo.isEmpty())  // 过滤null和空字符串
                .toList();

            Set<String> add =
                traceNoAddList.stream().filter(code -> !traceNoList.contains(code)).collect(Collectors.toSet());
            Set<String> subtract =
                traceNoList.stream().filter(code -> !traceNoAddList.contains(code)).collect(Collectors.toSet());

            // 合并结果到一个映射中
            Map<String, String> result = Stream
                .concat(add.stream().collect(Collectors.toMap(code -> code, code -> "add")).entrySet().stream(),
                    subtract.stream().collect(Collectors.toMap(code -> code, code -> "subtract")).entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

            for (Map.Entry<String, String> entry : result.entrySet()) {
                traceNoManage = new TraceNoManage();
                // 追溯码处理
                traceNoManage.setItemTable(supplyItemDetailDto.getItemTable())
                    // 项目id
                    .setItemId(supplyItemDetailDto.getItemId())
                    // 仓库类型
                    .setLocationTypeEnum(supplyItemDetailDto.getPurposeTypeEnum())
                    // 仓库
                    .setLocationId(supplyItemDetailDto.getPurposeLocationId())
                    // 仓位
                    .setLocationStoreId(supplyItemDetailDto.getPurposeLocationStoreId())
                    // 产品批号
                    .setLotNumber(supplyItemDetailDto.getLotNumber())
                    // 追溯码
                    .setTraceNo(entry.getKey())
                    // 追溯码单位
                    .setUnitCode(supplyItemDetailDto.getItemUnit())
                    // 操作类型
                    .setOperationType(operationType);
                if (Objects.equals(entry.getValue(), "add")) {
                    // 追溯码状态
                    traceNoManage.setStatusEnum(TraceNoStatus.IN.getValue());
                } else {
                    // 追溯码状态
                    traceNoManage.setStatusEnum(TraceNoStatus.OUT.getValue());
                }
                traceNoManageList.add(traceNoManage);
            }
        }

        return traceNoManageService.saveBatch(traceNoManageList);
    }
}
