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

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.core.common.core.domain.R;
import com.core.common.exception.ServiceException;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.ChargeItem;
import com.openhis.administration.service.IChargeItemService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.document.domain.RequestForm;
import com.openhis.document.service.IRequestFormService;
import com.openhis.web.doctorstation.dto.ActivityChildrenJsonParams;
import com.openhis.web.doctorstation.utils.AdviceUtils;
import com.openhis.web.regdoctorstation.appservice.IRequestFormManageAppService;
import com.openhis.web.regdoctorstation.dto.*;
import com.openhis.web.regdoctorstation.mapper.RequestFormManageAppMapper;
import com.openhis.workflow.domain.ActivityDefinition;
import com.openhis.workflow.domain.ServiceRequest;
import com.openhis.workflow.service.IActivityDefinitionService;
import com.openhis.workflow.service.IServiceRequestService;

import lombok.extern.slf4j.Slf4j;

/**
 * 申请单管理 应用实现类
 */
@Slf4j
@Service
public class RequestFormManageAppServiceImpl implements IRequestFormManageAppService {

    @Resource
    RequestFormManageAppMapper requestFormManageAppMapper;

    @Resource
    AssignSeqUtil assignSeqUtil;

    @Resource
    AdviceUtils adviceUtils;

    @Resource
    IRequestFormService iRequestFormService;

    @Resource
    IServiceRequestService iServiceRequestService;

    @Resource
    IChargeItemService iChargeItemService;

    @Resource
    IActivityDefinitionService iActivityDefinitionService;

    /**
     * 保存申请单
     *
     * @param requestFormSaveDto 申请单保存dto
     * @param typeCode 申请单类型
     * @return 结果
     */
    @Override
    public R<?> saveRequestForm(RequestFormSaveDto requestFormSaveDto, String typeCode) {
        // 诊疗处方号
        String prescriptionNo;
        // 申请单ID
        Long requestFormId = requestFormSaveDto.getRequestFormId();
        // 编辑场景
        if (requestFormId != null) {
            RequestForm requestFormInfo = iRequestFormService.getById(requestFormId);
            prescriptionNo = requestFormInfo.getPrescriptionNo();
            // 该申请单存在的待发送医嘱个数
            long count = iServiceRequestService.count(new LambdaQueryWrapper<ServiceRequest>()
                .eq(ServiceRequest::getStatusEnum, RequestStatus.DRAFT.getValue())
                .eq(ServiceRequest::getPrescriptionNo, prescriptionNo));
            if (count == 0L) {
                return R.fail("无待签发的医嘱,该申请单不可编辑");
            }
        } else {
            // 诊疗处方号
            prescriptionNo = assignSeqUtil.getSeq(AssignSeqEnum.ACTIVITY_PSYCHOTROPIC_NO.getPrefix(), 8);
        }

        // 当前时间
        Date curDate = new Date();
        // 请求类型
        Integer categoryEnum = requestFormSaveDto.getCategoryEnum();
        // 当前登录账号的科室id
        Long orgId = SecurityUtils.getLoginUser().getOrgId();
        // 当前参与者ID
        Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
        // 就诊ID
        Long encounterId = requestFormSaveDto.getEncounterId();
        // 患者ID
        Long patientId = requestFormSaveDto.getPatientId();
        // 患者挂号对应的科室id 或 住院科室id
        Long organizationId = requestFormSaveDto.getOrganizationId();

        // 声明申请单信息
        RequestForm requestForm = new RequestForm();
        requestForm.setId(requestFormId);
        requestForm.setTypeCode(typeCode); // 申请单类型
        requestForm.setPrescriptionNo(prescriptionNo); // 处方号
        requestForm.setName(requestFormSaveDto.getName()); // 名称
        requestForm.setEncounterId(encounterId); // 就诊ID
        requestForm.setRequesterId(practitionerId); // 申请人
        requestForm.setDescJson(requestFormSaveDto.getDescJson()); // 描述内容
        iRequestFormService.saveOrUpdate(requestForm);

        // 编辑场景时,先删除掉原有诊疗项目及账单再新增
        if (requestFormId != null) {
            List<Long> serviceRequestIds = iServiceRequestService
                .list(new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getPrescriptionNo, prescriptionNo))
                .stream().map(ServiceRequest::getId).collect(Collectors.toList());
            for (Long serviceRequestId : serviceRequestIds) {
                iServiceRequestService.removeById(serviceRequestId);
                // 删除费用项
                iChargeItemService.deleteByServiceTableAndId(CommonConstants.TableName.WOR_SERVICE_REQUEST,
                    serviceRequestId);
            }
        }

        ServiceRequest serviceRequest;
        ChargeItem chargeItem;
        // 诊疗集合
        List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
        // 诊疗执行科室配置
        List<ActivityOrganizationConfigDto> activityOrganizationConfig =
            requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
        if (activityOrganizationConfig.isEmpty()) {
            throw new ServiceException("请先配置当前时间段的执行科室");
        }

        for (ActivitySaveDto activitySaveDto : activityList) {
            serviceRequest = new ServiceRequest();
            serviceRequest.setStatusEnum(RequestStatus.DRAFT.getValue());
            serviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4));
            serviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
            serviceRequest.setPrescriptionNo(prescriptionNo);
            serviceRequest.setTherapyEnum(TherapyTimeType.TEMPORARY.getValue());// 治疗类型
            serviceRequest.setQuantity(activitySaveDto.getQuantity()); // 请求数量
            serviceRequest.setUnitCode(activitySaveDto.getUnitCode()); // 请求单位编码
            serviceRequest.setCategoryEnum(categoryEnum); // 请求类型
            serviceRequest.setActivityId(activitySaveDto.getAdviceDefinitionId());// 诊疗定义id
            serviceRequest.setPatientId(patientId); // 患者
            serviceRequest.setRequesterId(practitionerId); // 开方医生
            serviceRequest.setEncounterId(encounterId); // 就诊id
            serviceRequest.setAuthoredTime(curDate); // 请求签发时间

            Long positionId = activityOrganizationConfig.stream()
                .filter(dto -> activitySaveDto.getAdviceDefinitionId().equals(dto.getActivityDefinitionId()))
                .map(ActivityOrganizationConfigDto::getOrganizationId).findFirst().orElse(null);
            if (positionId == null) {
                throw new ServiceException(activitySaveDto.getAdviceDefinitionName() + "未配置当前时间段的执行科室");
            }
            serviceRequest.setOrgId(positionId); // 执行科室

            serviceRequest.setYbClassEnum(activitySaveDto.getYbClassEnum());// 类别医保编码
            serviceRequest.setConditionId(activitySaveDto.getConditionId()); // 诊断id
            serviceRequest.setEncounterDiagnosisId(activitySaveDto.getEncounterDiagnosisId()); // 就诊诊断id
            iServiceRequestService.save(serviceRequest);

            chargeItem = new ChargeItem();
            chargeItem.setStatusEnum(ChargeItemStatus.DRAFT.getValue()); // 收费状态
            chargeItem.setBusNo(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(serviceRequest.getBusNo()));
            chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
            chargeItem.setPatientId(patientId); // 患者
            chargeItem.setContextEnum(activitySaveDto.getAdviceType()); // 类型
            chargeItem.setEncounterId(encounterId); // 就诊id
            chargeItem.setDefinitionId(activitySaveDto.getDefinitionId()); // 费用定价ID
            chargeItem.setDefDetailId(activitySaveDto.getDefinitionDetailId()); // 定价子表主键
            chargeItem.setEntererId(practitionerId);// 开立人ID
            chargeItem.setEnteredDate(curDate); // 开立时间
            chargeItem.setServiceTable(CommonConstants.TableName.WOR_SERVICE_REQUEST);// 医疗服务类型
            chargeItem.setServiceId(serviceRequest.getId()); // 医疗服务ID
            chargeItem.setProductTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION);// 产品所在表
            chargeItem.setProductId(activitySaveDto.getAdviceDefinitionId());// 收费项id
            chargeItem.setAccountId(activitySaveDto.getAccountId());// 关联账户ID
            chargeItem.setRequestingOrgId(orgId); // 开立科室
            chargeItem.setConditionId(activitySaveDto.getConditionId()); // 诊断id
            chargeItem.setEncounterDiagnosisId(activitySaveDto.getEncounterDiagnosisId()); // 就诊诊断id
            chargeItem.setQuantityValue(activitySaveDto.getQuantity()); // 数量
            chargeItem.setQuantityUnit(activitySaveDto.getUnitCode()); // 单位
            chargeItem.setUnitPrice(activitySaveDto.getUnitPrice()); // 单价
            chargeItem.setTotalPrice(activitySaveDto.getTotalPrice()); // 总价
            iChargeItemService.save(chargeItem);

            // 处理诊疗套餐的子项信息
            ActivityDefinition activityDefinition =
                iActivityDefinitionService.getById(activitySaveDto.getAdviceDefinitionId());
            String childrenJson = activityDefinition.getChildrenJson();
            if (childrenJson != null) {
                // 诊疗子项参数类
                ActivityChildrenJsonParams activityChildrenJsonParams = new ActivityChildrenJsonParams();
                activityChildrenJsonParams.setTherapyEnum(TherapyTimeType.TEMPORARY.getValue()); // 治疗类型
                activityChildrenJsonParams.setPatientId(serviceRequest.getPatientId()); // 患者
                activityChildrenJsonParams.setEncounterId(serviceRequest.getEncounterId()); // 就诊id
                activityChildrenJsonParams.setAccountId(chargeItem.getAccountId()); // 账户id
                activityChildrenJsonParams.setChargeItemId(chargeItem.getId()); // 费用项id
                activityChildrenJsonParams.setParentId(serviceRequest.getId());// 子项诊疗的父id
                adviceUtils.handleActivityChild(childrenJson, organizationId, activityChildrenJsonParams);
            }
        }

        return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"申请单"}));
    }

    /**
     * 查询申请单
     *
     * @param encounterId 就诊id
     * @param typeCode 申请单类型
     * @return 检查申请单
     */
    @Override
    public List<RequestFormQueryDto> getRequestForm(Long encounterId, String typeCode) {
        List<RequestFormQueryDto> requestFormList = requestFormManageAppMapper.getRequestForm(encounterId, typeCode);
        for (RequestFormQueryDto requestFormQueryDto : requestFormList) {
            // 查询处方详情
            List<RequestFormDetailQueryDto> requestFormDetail =
                requestFormManageAppMapper.getRequestFormDetail(requestFormQueryDto.getPrescriptionNo());
            requestFormQueryDto.setRequestFormDetailList(requestFormDetail);
        }
        return requestFormList;
    }

}
