package com.openhis.medication.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

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.AssignSeqUtil;
import com.core.common.utils.DateUtils;
import com.openhis.common.enums.AssignSeqEnum;
import com.openhis.common.enums.DbOpType;
import com.openhis.common.enums.DelFlag;
import com.openhis.common.enums.DispenseStatus;
import com.openhis.medication.domain.MedicationDispense;
import com.openhis.medication.domain.MedicationRequest;
import com.openhis.medication.mapper.MedicationDispenseMapper;
import com.openhis.medication.service.IMedicationDispenseService;

/**
 * 药品发放管理Service业务层处理
 *
 * @author system
 * @date 2025-02-20
 */
@Service
public class MedicationDispenseServiceImpl extends ServiceImpl<MedicationDispenseMapper, MedicationDispense>
    implements IMedicationDispenseService {

    @Resource
    AssignSeqUtil assignSeqUtil;

    /**
     * 处理药品发放信息
     *
     * @param medicationRequest 药品请求信息
     * @param dbOpType db操作类型
     * @return 发放id
     */
    @Override
    public Long handleMedicationDispense(MedicationRequest medicationRequest, String dbOpType) {
        MedicationDispense medicationDispense = new MedicationDispense();
        // 药品发放id
        medicationDispense.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_DIS_NO.getPrefix(), 4));
        // 药品发放状态
        medicationDispense.setStatusEnum(DispenseStatus.DRAFT.getValue());
        // 状态变更时间
        medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
        // 发药类型
        medicationDispense.setDispenseEnum(medicationRequest.getCategoryEnum());
        // 药品编码
        medicationDispense.setMedicationId(medicationRequest.getMedicationId());
        // 请求数量
        medicationDispense.setQuantity(medicationRequest.getQuantity());
        // 请求单位编码
        medicationDispense.setUnitCode(medicationRequest.getUnitCode());
        // 产品批号
        medicationDispense.setLotNumber(medicationRequest.getLotNumber());
        // 患者id
        medicationDispense.setPatientId(medicationRequest.getPatientId());
        // 就诊id
        medicationDispense.setEncounterId(medicationRequest.getEncounterId());
        // 支持用药信息
        medicationDispense.setSupportInfo(medicationRequest.getSupportInfo());
        // 发药人
        medicationDispense.setPractitionerId(medicationRequest.getPractitionerId());
        // 发放药房
        medicationDispense.setLocationId(medicationRequest.getPerformLocation());
        // 药品请求id
        medicationDispense.setMedReqId(medicationRequest.getId());
        // 已发药数量
        medicationDispense.setDispenseQuantity(BigDecimal.ZERO);
        // 用法
        medicationDispense.setMethodCode(medicationRequest.getMethodCode());
        // 用药频次
        medicationDispense.setFrequencyCode(medicationRequest.getRateCode());
        // 单次剂量
        medicationDispense.setDose(medicationRequest.getDose());
        // 剂量单位
        medicationDispense.setDoseUnitCode(medicationRequest.getDoseUnitCode());
        // 单次最大剂量
        medicationDispense.setMaxUnit(medicationRequest.getMaxDose());

        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 增加2小时
        LocalDateTime newTime = now.plusHours(2);
        // 转换为Date对象（如果需要保持使用Date类型）
        Date limitTime = Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant());
        // 设置限制发药时间
        medicationDispense.setLimitTime(limitTime);

        if (DbOpType.INSERT.getCode().equals(dbOpType)) {
            baseMapper.insert(medicationDispense);
        } else if (DbOpType.UPDATE.getCode().equals(dbOpType)) {
            baseMapper.update(medicationDispense, new LambdaUpdateWrapper<MedicationDispense>()
                .eq(MedicationDispense::getMedReqId, medicationRequest.getId()));
        }

        return medicationDispense.getId();
    }

    /**
     * 医嘱执行生成药品发放,状态为待配药
     *
     * @param medicationRequest 药品医嘱请求
     * @param procedureId 执行记录id
     * @param plannedDispenseTime 预定发药时间
     * @return 发放id
     */
    @Override
    public Long generateMedicationDispense(MedicationRequest medicationRequest, Long procedureId,
        Date plannedDispenseTime) {
        MedicationDispense medicationDispense = new MedicationDispense();
        // 执行id
        medicationDispense.setProcedureId(procedureId);
        // 预定发药时间
        medicationDispense.setPlannedDispenseTime(plannedDispenseTime);
        // 药品发放id
        medicationDispense.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_DIS_NO.getPrefix(), 4));
        // 药品发放状态
        medicationDispense.setStatusEnum(DispenseStatus.PREPARATION.getValue());
        // 状态变更时间
        medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
        // 发药类型
        medicationDispense.setDispenseEnum(medicationRequest.getCategoryEnum());
        // 药品编码
        medicationDispense.setMedicationId(medicationRequest.getMedicationId());
        // 请求数量
        medicationDispense.setQuantity(medicationRequest.getQuantity());
        // 请求单位编码
        medicationDispense.setUnitCode(medicationRequest.getUnitCode());
        // 产品批号
        medicationDispense.setLotNumber(medicationRequest.getLotNumber());
        // 患者id
        medicationDispense.setPatientId(medicationRequest.getPatientId());
        // 就诊id
        medicationDispense.setEncounterId(medicationRequest.getEncounterId());
        // 支持用药信息
        medicationDispense.setSupportInfo(medicationRequest.getSupportInfo());
        // 发药人
        medicationDispense.setPractitionerId(medicationRequest.getPractitionerId());
        // 发放药房
        medicationDispense.setLocationId(medicationRequest.getPerformLocation());
        // 药品请求id
        medicationDispense.setMedReqId(medicationRequest.getId());
        // 已发药数量
        medicationDispense.setDispenseQuantity(BigDecimal.ZERO);
        // 用法
        medicationDispense.setMethodCode(medicationRequest.getMethodCode());
        // 用药频次
        medicationDispense.setFrequencyCode(medicationRequest.getRateCode());
        // 单次剂量
        medicationDispense.setDose(medicationRequest.getDose());
        // 剂量单位
        medicationDispense.setDoseUnitCode(medicationRequest.getDoseUnitCode());
        // 单次最大剂量
        medicationDispense.setMaxUnit(medicationRequest.getMaxDose());
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 增加12小时
        LocalDateTime newTime = now.plusHours(12);
        // 转换为Date对象（如果需要保持使用Date类型）
        Date limitTime = Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant());
        // 设置限制发药时间
        medicationDispense.setLimitTime(limitTime);

        baseMapper.insert(medicationDispense);

        return medicationDispense.getId();
    }

    /**
     * 删除药品发放信息
     *
     * @param medReqId 药品请求id
     */
    @Override
    public void deleteMedicationDispense(Long medReqId) {
        baseMapper.delete(new LambdaQueryWrapper<MedicationDispense>().eq(MedicationDispense::getMedReqId, medReqId));
    }

    /**
     * 更新未发放药品状态：停止发放
     *
     * @param medDisIdList 发放id列表
     * @param refund 停止原因：退费
     */
    @Override
    public void updateStopDispenseStatus(List<Long> medDisIdList, Integer refund) {
        baseMapper.update(
            new MedicationDispense().setStatusEnum(DispenseStatus.STOPPED.getValue()).setNotPerformedReasonEnum(refund),
            new LambdaUpdateWrapper<MedicationDispense>().in(MedicationDispense::getId, medDisIdList));
    }

    /**
     * 更新药品状态：待配药
     *
     * @param medicationRequestIdList 请求id列表
     */
    @Override
    public void updatePreparationDispenseStatus(List<Long> medicationRequestIdList) {
        baseMapper.update(null,
            new LambdaUpdateWrapper<MedicationDispense>()
                .set(MedicationDispense::getStatusEnum, DispenseStatus.PREPARATION.getValue())
                .set(MedicationDispense::getStatusChangedTime, DateUtils.getNowDate())
                .in(MedicationDispense::getMedReqId, medicationRequestIdList));
    }

    /**
     * 更新药品状态：暂停
     *
     * @param medReqIdList 请求id列表
     */
    @Override
    public void updateOnHoldDispenseStatus(List<Long> medReqIdList) {
        baseMapper.update(null,
            new LambdaUpdateWrapper<MedicationDispense>()
                .set(MedicationDispense::getStatusEnum, DispenseStatus.ON_HOLD.getValue())
                .set(MedicationDispense::getStatusChangedTime, DateUtils.getNowDate())
                .in(MedicationDispense::getMedReqId, medReqIdList));
    }

    /**
     * 验证是否发过药
     *
     * @param medicationDefId 药品定义id
     * @return 验证结果
     */
    @Override
    public boolean verifyAbleEdit(Long medicationDefId) {
        return baseMapper.exists(
            new LambdaQueryWrapper<MedicationDispense>().eq(MedicationDispense::getMedicationId, medicationDefId)
                .and(q -> q.eq(MedicationDispense::getStatusEnum, DispenseStatus.COMPLETED.getValue()).or()
                    .eq(MedicationDispense::getStatusEnum, DispenseStatus.REFUNDED.getValue()))
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 通过请求id获取药品发放信息
     *
     * @param requestIdList 请求id
     * @return 发放信息
     */
    @Override
    public List<MedicationDispense> selectByRequestIdList(List<Long> requestIdList) {
        return baseMapper
            .selectList(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getMedReqId, requestIdList)
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 更新药品状态：已汇总
     *
     * @param medDispenseId 发放id列表
     */
    @Override
    public void updateDispenseStatusSummarized(List<Long> medDispenseId, String busNo) {
        baseMapper.update(null,
            new LambdaUpdateWrapper<MedicationDispense>()
                .set(MedicationDispense::getStatusEnum, DispenseStatus.SUMMARIZED.getValue())
                .set(MedicationDispense::getStatusChangedTime, DateUtils.getNowDate())
                .set(MedicationDispense::getSummaryNo, busNo).in(MedicationDispense::getId, medDispenseId)
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 通过执行id获取药品发放信息
     *
     * @param procedureIdList 执行id列表
     * @return 发放信息
     */
    @Override
    public List<MedicationDispense> getMedDispenseByProcedureId(List<Long> procedureIdList) {
        return baseMapper.selectList(
            new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getProcedureId, procedureIdList)
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 取消汇总
     *
     * @param summaryNoList 汇总单号
     * @return 取消结果
     */
    @Override
    public boolean cancelMedicationSummary(List<String> summaryNoList) {
        int result = baseMapper.update(null,
            new LambdaUpdateWrapper<MedicationDispense>()
                .set(MedicationDispense::getStatusEnum, DispenseStatus.PREPARATION.getValue())
                .set(MedicationDispense::getSummaryNo, null).in(MedicationDispense::getSummaryNo, summaryNoList)
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
        return result > 0;
    }

    /**
     * 更新药品发放状态
     *
     * @param dispenseIdList 发放id列表
     * @param dispenseStatus 发放状态
     */
    @Override
    public void updateDispenseStatus(List<Long> dispenseIdList, Integer dispenseStatus) {
        baseMapper.update(null,
            new LambdaUpdateWrapper<MedicationDispense>().set(MedicationDispense::getStatusEnum, dispenseStatus)
                .set(MedicationDispense::getStatusChangedTime, DateUtils.getNowDate())
                .in(MedicationDispense::getId, dispenseIdList)
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 通过汇总单号获取药品发放信息
     *
     * @param summaryNoList 汇总单号列表
     * @return 发放信息
     */
    @Override
    public List<MedicationDispense> getMedDispenseBySummaryNo(List<String> summaryNoList) {
        return baseMapper
            .selectList(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getSummaryNo, summaryNoList)
                .eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
    }
}