package com.openhis.workflow.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.core.common.utils.DateUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.enums.DelFlag;
import com.openhis.common.enums.SupplyCategory;
import com.openhis.common.enums.SupplyStatus;
import com.openhis.common.enums.SupplyType;
import com.openhis.medication.dto.AdjustPriceMedListDto;
import com.openhis.workflow.domain.SupplyRequest;
import com.openhis.workflow.dto.ChangePriceDto;
import com.openhis.workflow.mapper.SupplyRequestMapper;
import com.openhis.workflow.service.ISupplyRequestService;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 供应申请管理Service业务层处理
 *
 * @author system
 * @date 2025-02-20
 */
@Slf4j
@Service
@AllArgsConstructor
public class SupplyRequestServiceImpl extends ServiceImpl<SupplyRequestMapper, SupplyRequest>
    implements ISupplyRequestService {
    @Resource
    private SupplyRequestMapper supplyRequestMapper;

    /**
     * 通过单据号查询单据信息
     *
     * @param busNo 单据号
     * @return 单据信息
     */
    @Override
    public List<SupplyRequest> getSupplyByBusNo(String busNo) {
        return baseMapper.selectList(new LambdaQueryWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo));
    }

    /**
     * 通过原始单据号查询单据信息
     *
     * @param originalBusNo 原始单据号
     * @return 单据信息
     */
    @Override
    public List<SupplyRequest> getSupplyByOriginalBusNo(String originalBusNo) {
        return baseMapper
            .selectList(new LambdaQueryWrapper<SupplyRequest>().eq(SupplyRequest::getOriginalBusNo, originalBusNo));
    }

    /**
     * 同意申请
     *
     * @param busNo 单据号
     * @param now 当前时间
     * @return 单据详情
     */
    @Override
    public List<SupplyRequest> agreeRequest(String busNo, Date now) {
        // 更新单据状态
        baseMapper.update(null,
            new LambdaUpdateWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo)
                .set(SupplyRequest::getApprovalTime, now)
                .set(SupplyRequest::getApproverId, SecurityUtils.getLoginUser().getPractitionerId())
                .set(SupplyRequest::getStatusEnum, SupplyStatus.AGREE.getValue()));
        // 返回单据详情
        return this.getSupplyByBusNo(busNo);
    }

    /**
     * 添加原始单据号
     *
     * @param busNo 单据号
     * @param originalBusNo 原始单据号
     * @return 单据详情
     */
    @Override
    public List<SupplyRequest> addOriginalBusNo(String busNo, String originalBusNo) {
        // 更新单据状态
        baseMapper.update(null, new LambdaUpdateWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo)
            .set(SupplyRequest::getOriginalBusNo, originalBusNo));
        // 返回单据详情
        return this.getSupplyByBusNo(busNo);
    }

    /**
     * 将原始单据号信息的原始单据号删除
     *
     * @param busNo 单据号
     * @return 单据详情
     */
    @Override
    public boolean updateByBusNo(String busNo) {
        int updateCount = baseMapper.update(null, new LambdaUpdateWrapper<SupplyRequest>()
            .eq(SupplyRequest::getBusNo, busNo).set(SupplyRequest::getOriginalBusNo, ""));
        return updateCount > 0;
    }

    /**
     * 将原始单据号信息的状态改为已失效
     *
     * @param busNo 单据号
     * @return 单据详情
     */
    @Override
    public boolean updateStatusEnumByBusNo(String busNo) {
        int updateCount =
            baseMapper.update(null, new LambdaUpdateWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo)
                .set(SupplyRequest::getStatusEnum, SupplyStatus.EXPIRED_INVALIDATED.getValue()));
        return updateCount > 0;
    }

    /**
     * 提交审批
     *
     * @param busNo 单据号
     * @return 操作结果
     */
    @Override
    public boolean submitApproval(String busNo) {
        int updateCount = baseMapper.update(null,
            new LambdaUpdateWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo)
                .set(SupplyRequest::getApplyTime, DateUtils.getNowDate())
                .set(SupplyRequest::getStatusEnum, SupplyStatus.APPROVAL.getValue()));
        return updateCount > 0;
    }

    /**
     * 撤回
     *
     * @param busNo 单据号
     * @return 操作结果
     */
    @Override
    public boolean withdrawApproval(String busNo) {
        int updateCount = baseMapper.update(null,
            new LambdaUpdateWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo)
                .set(SupplyRequest::getApplyTime, DateUtils.getNowDate())
                .set(SupplyRequest::getStatusEnum, SupplyStatus.WITHDRAW.getValue()));
        return updateCount > 0;
    }

    /**
     * 删除单据
     *
     * @param busNo 单据号
     * @return 操作结果
     */
    @Override
    public boolean removeByBusNo(String busNo) {
        int updateCount = baseMapper.update(null, new LambdaUpdateWrapper<SupplyRequest>()
            .eq(SupplyRequest::getBusNo, busNo).set(SupplyRequest::getDeleteFlag, DelFlag.YES.getCode()));
        return updateCount > 0;
    }

    /**
     * 驳回申请
     *
     * @param busNo 单据号
     */
    @Override
    public boolean rejectRequest(String busNo) {
        // 更新单据状态
        int updateCount = baseMapper.update(null,
            new LambdaUpdateWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo)
                .set(SupplyRequest::getApprovalTime, DateUtils.getNowDate())
                .set(SupplyRequest::getApproverId, SecurityUtils.getLoginUser().getPractitionerId())
                .set(SupplyRequest::getStatusEnum, SupplyStatus.REJECT.getValue()));
        return updateCount > 0;
    }

    /**
     * 获取供应项目所在表
     *
     * @param agreedList 供应单据信息
     * @return 供应项目所在表
     */
    @Override
    public String getItemTable(List<SupplyRequest> agreedList) {
        return agreedList.stream().map(SupplyRequest::getItemTable).findFirst().orElse(null);
    }

    /**
     * 获取供应的物品
     *
     * @param agreedList 供应单据
     * @return 物品id
     */
    @Override
    public List<Long> getItem(List<SupplyRequest> agreedList) {
        return agreedList.stream().map(SupplyRequest::getItemId).collect(Collectors.toList());
    }

    /**
     * 校验(已经审批通过的单号(请求状态是同意),不能再重复编辑请求)
     *
     * @param busNo 单据号
     */
    @Override
    public boolean supplyRequestValidation(String busNo) {

        // 根据单据号查询请求状态
        List<SupplyRequest> requestList =
            baseMapper.selectList(new LambdaQueryWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo));
        if (!requestList.isEmpty()) {
            for (SupplyRequest supplyRequest : requestList) {
                if (SupplyStatus.AGREE.getValue().equals(supplyRequest.getStatusEnum())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 验证是否发生过业务
     *
     * @param itemId 项目id
     * @return 校验结果
     */
    @Override
    public boolean verifyAbleEdit(Long itemId) {
        return baseMapper.exists(new LambdaQueryWrapper<SupplyRequest>().eq(SupplyRequest::getItemId, itemId)
            .eq(SupplyRequest::getDeleteFlag, DelFlag.NO.getCode())
            .in(SupplyRequest::getStatusEnum, SupplyStatus.APPROVAL.getValue(), SupplyStatus.AGREE.getValue()));
    }

    /**
     * 通过单据号删除单据信息
     *
     * @param busNo 单据号
     */
    @Override
    public boolean deleteRequest(String busNo) {
        // 更新单据状态
        int deleteCount = baseMapper.delete(new LambdaQueryWrapper<SupplyRequest>().eq(SupplyRequest::getBusNo, busNo));

        return deleteCount > 0;
    }

    /**
     * 更新请求状态：同意
     *
     * @param supplyRequestIdList 供应申请id列表
     */
    @Override
    public void updateCompletedStatusBatch(List<Long> supplyRequestIdList) {
        baseMapper.update(new SupplyRequest().setStatusEnum(SupplyStatus.AGREE.getValue())
            .setApproverId(SecurityUtils.getLoginUser().getPractitionerId()).setApprovalTime(DateUtils.getNowDate()),
            new LambdaUpdateWrapper<SupplyRequest>().in(SupplyRequest::getId, supplyRequestIdList));
    }

    /**
     * 根据id，获取供应申请列表
     *
     * @param requestIdList id列表
     * @return 供应发放列表
     */
    @Override
    public List<SupplyRequest> selectByIdList(List<Long> requestIdList) {
        return baseMapper.selectList(new LambdaQueryWrapper<SupplyRequest>().in(SupplyRequest::getId, requestIdList)
            .eq(SupplyRequest::getDeleteFlag, DelFlag.NO.getCode()));
    }

    @Override
    public List<ChangePriceDto> searchDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchDataForBusNo(busNo);
    }

    /**
     * 生成汇总发药单
     *
     * @param medicationId
     * @param locationId
     * @param lotNumber
     * @param patientId
     * @param minQuantity
     * @param minUnitCode
     * @param practitionerId
     * @param now
     * @param busNo
     */
    @Override
    public Long createSummarySupplyRequest(Long medicationId, Long locationId, String lotNumber, Long patientId,
        BigDecimal minQuantity, String minUnitCode, Long practitionerId, Date now, String busNo) {
        SupplyRequest supplyRequest = new SupplyRequest().setItemId(medicationId).setSourceLocationId(locationId)
            .setLotNumber(lotNumber).setPatientId(patientId).setItemQuantity(minQuantity).setUnitCode(minUnitCode)
            .setApplicantId(practitionerId).setApplyTime(now).setBusNo(busNo)
            .setStatusEnum(SupplyStatus.SEND.getValue()).setTypeEnum(SupplyType.SUMMARY_DISPENSE.getValue())
            .setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
            .setCategoryEnum(SupplyCategory.STOCK_SUPPLY.getValue());
        baseMapper.insert(supplyRequest);
        return supplyRequest.getId();
    }

    /**
     * 生成汇总发药单
     *
     * @param deviceId
     * @param locationId
     * @param lotNumber
     * @param minQuantity
     * @param minUnitCode
     * @param practitionerId
     * @param now
     * @param busNo
     */
    @Override
    public Long createDeviceSummarySupplyRequest(Long deviceId, Long locationId, String lotNumber,
        BigDecimal minQuantity, String minUnitCode, Long practitionerId, Date now, String busNo) {
        SupplyRequest supplyRequest = new SupplyRequest().setItemId(deviceId).setSourceLocationId(locationId)
            .setLotNumber(lotNumber).setItemQuantity(minQuantity).setUnitCode(minUnitCode)
            .setApplicantId(practitionerId).setApplyTime(now).setBusNo(busNo)
            .setStatusEnum(SupplyStatus.SEND.getValue()).setTypeEnum(SupplyType.DEVICE_STOCKTAKING.getValue())
            .setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
            .setCategoryEnum(SupplyCategory.STOCK_SUPPLY.getValue());
        baseMapper.insert(supplyRequest);
        return supplyRequest.getId();
    }

    @Override
    public List<AdjustPriceMedListDto> searchMedInfoDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchMedInfoDataForBusNo(busNo);
    }

    @Override
    public List<AdjustPriceMedListDto> searchHistoryMedInfoData(String busNo, Date createTime) {
        return this.supplyRequestMapper.searchHistoryMedInfoData(busNo, createTime);
    }

    @Override
    public List<AdjustPriceMedListDto> searchDeviceInfoDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchDeviceInfoDataForBusNo(busNo);
    }

    @Override
    public List<AdjustPriceMedListDto> searchHistoryDeviceInfoDataForBusNo(String busNo, Date createTime) {
        return this.supplyRequestMapper.searchHistoryDeviceInfoDataForBusNo(busNo, createTime);
    }

    @Override
    public List<AdjustPriceMedListDto> searchActivityInfoDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchActivityInfoDataForBusNo(busNo);
    }

    @Override
    public List<AdjustPriceMedListDto> searchHistoryActivityInfoDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchHistoryActivityInfoDataForBusNo(busNo);
    }

    @Override
    public List<AdjustPriceMedListDto> searchHealthInfoDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchHealthInfoDataForBusNo(busNo);
    }

    @Override
    public List<AdjustPriceMedListDto> searchHistoryHealthInfoDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchHistoryHealthInfoDataForBusNo(busNo);
    }

    /**
     * 取消汇总
     *
     * @param summaryNoList 汇总单号
     * @return 汇总单ids
     */
    @Override
    public List<Long> cancelSummarySupplyRequest(List<String> summaryNoList) {
        // 查询汇总发药单
        List<SupplyRequest> supplyRequestList =
            baseMapper.selectList(new LambdaQueryWrapper<SupplyRequest>().in(SupplyRequest::getBusNo, summaryNoList)
                .eq(SupplyRequest::getTypeEnum, SupplyType.SUMMARY_DISPENSE.getValue())
                .eq(SupplyRequest::getDeleteFlag, DelFlag.NO.getCode()));
        // 软删除汇总发药单
        baseMapper.delete(new LambdaQueryWrapper<SupplyRequest>().in(SupplyRequest::getBusNo, summaryNoList)
            .eq(SupplyRequest::getTypeEnum, SupplyType.SUMMARY_DISPENSE.getValue()));
        if (supplyRequestList != null && !supplyRequestList.isEmpty()) {
            return supplyRequestList.stream().map(SupplyRequest::getId).toList();
        }
        return null;
    }

    @Override
    public List<ChangePriceDto> searchGroupDataForBusNo(String busNo) {
        return this.supplyRequestMapper.searchGroupDataForBusNo(busNo);
    }
}