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

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

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

import cn.hutool.core.util.ObjectUtil;
import com.openhis.web.doctorstation.appservice.*;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.utils.AgeCalculatorUtil;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.Encounter;
import com.openhis.administration.domain.EncounterParticipant;
import com.openhis.administration.mapper.EncounterMapper;
import com.openhis.administration.service.IEncounterParticipantService;
import com.openhis.common.enums.*;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.web.doctorstation.dto.PatientInfoDto;
import com.openhis.web.doctorstation.dto.PrescriptionInfoBaseDto;
import com.openhis.web.doctorstation.dto.PrescriptionInfoDetailDto;
import com.openhis.web.doctorstation.mapper.DoctorStationMainAppMapper;

/**
 * 医生站-主页面 应用实现类
 */
@Service
public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppService {

    @Resource
    DoctorStationMainAppMapper doctorStationMainAppMapper;

    @Resource
    EncounterMapper encounterMapper;

    @Resource
    IEncounterParticipantService iEncounterParticipantService;

    @Resource
    IDoctorStationAdviceAppService iDoctorStationAdviceAppService;

    @Resource
    IDoctorStationEmrAppService iDoctorStationEmrAppService;

    @Resource
    IDoctorStationDiagnosisAppService  iDoctorStationDiagnosisAppService;

    @Resource
    IDoctorStationChineseMedicalAppService iDoctorStationChineseMedicalAppService;
    /**
     * 查询就诊患者信息
     *
     * @param patientInfoDto 查询条件 (前端传 statusEnum 区分就诊状态tab)
     * @param searchKey 模糊查询关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @param pricingFlag 划价标记
     * @return 就诊患者信息
     */
    @Override
    public IPage<PatientInfoDto> getPatientInfo(PatientInfoDto patientInfoDto, String searchKey, Integer pageNo,
        Integer pageSize, HttpServletRequest request, Integer pricingFlag) {
        // 当前登录账号ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        Long currentUserOrganizationId = SecurityUtils.getLoginUser().getOrgId();
        // 在诊的情况,需要参与者账户id(接诊医生)的条件
        if (EncounterStatus.IN_PROGRESS.getValue().equals(patientInfoDto.getStatusEnum())) {
            patientInfoDto.setJzPractitionerUserId(userId);
        }
        // 划价时
        if (Whether.YES.getValue().equals(pricingFlag)) {
            userId = null;
            currentUserOrganizationId = null;
        }
        // 构建查询条件
        QueryWrapper<PatientInfoDto> queryWrapper = HisQueryUtils.buildQueryWrapper(patientInfoDto, searchKey,
            new HashSet<>(Arrays.asList("patient_name", "id_card", "phone")), request);
        // 现诊列表按接诊时间倒序
        if (EncounterStatus.IN_PROGRESS.getValue().equals(patientInfoDto.getStatusEnum())) {
            queryWrapper.orderByDesc("reception_time");
        } else {
            queryWrapper.orderByDesc("register_time");
        }
        IPage<PatientInfoDto> patientInfo = doctorStationMainAppMapper.getPatientInfo(new Page<>(pageNo, pageSize),
            ParticipantType.REGISTRATION_DOCTOR.getCode(), ParticipantType.ADMITTER.getCode(),
            ClinicalStatus.INACTIVE.getValue(), userId, currentUserOrganizationId, pricingFlag,
            EncounterStatus.PLANNED.getValue(), EncounterActivityStatus.ACTIVE.getValue(), queryWrapper);
        patientInfo.getRecords().forEach(e -> {
            // 性别
            e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum()));
            // 计算年龄
            e.setAge(e.getBirthDate() != null ? AgeCalculatorUtil.getAge(e.getBirthDate()) : "");
            // 就诊状态
            e.setStatusEnum_enumText(EnumUtils.getInfoByValue(EncounterStatus.class, e.getStatusEnum()));
        });
        return patientInfo;
    }

    /**
     * 医生接诊
     *
     * @param encounterId 就诊id
     * @return 结果
     */
    @Override
    public R<?> receiveEncounter(Long encounterId) {
        int update = encounterMapper.update(null,
            new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
                .set(Encounter::getReceptionTime, new Date())
                .set(Encounter::getStatusEnum, EncounterStatus.IN_PROGRESS.getValue())
                .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.RECEIVING_CARE.getValue()));
        // 先把之前的接诊记录更新为已完成
        iEncounterParticipantService.update(new LambdaUpdateWrapper<EncounterParticipant>()
            .eq(EncounterParticipant::getTypeCode, ParticipantType.ADMITTER.getCode())
            .eq(EncounterParticipant::getEncounterId, encounterId)
            .set(EncounterParticipant::getStatusEnum, EncounterActivityStatus.COMPLETED.getValue()));

        // 插入接诊医生参与记录
        EncounterParticipant encounterParticipant = new EncounterParticipant();
        encounterParticipant.setEncounterId(encounterId);
        encounterParticipant.setTypeCode(ParticipantType.ADMITTER.getCode());// 接诊医生
        encounterParticipant.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
        encounterParticipant.setStatusEnum(EncounterActivityStatus.ACTIVE.getValue()); // 状态
        iEncounterParticipantService.save(encounterParticipant);
        return update > 0 ? R.ok() : R.fail();
    }

    /**
     * 患者暂离
     *
     * @param encounterId 就诊id
     * @return 结果
     */
    @Override
    public R<?> leaveEncounter(Long encounterId) {
        int update = encounterMapper.update(null,
            new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
                .set(Encounter::getStatusEnum, EncounterStatus.ON_HOLD.getValue())
                .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.ON_LEAVE.getValue()));
        return update > 0 ? R.ok() : R.fail();
    }

    /**
     * 就诊完成
     *
     * @param encounterId 就诊id
     * @return 结果
     */
    @Override
    public R<?> completeEncounter(Long encounterId) {
        int update = encounterMapper.update(null,
            new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
                .set(Encounter::getStatusEnum, EncounterStatus.DISCHARGED.getValue())
                .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.DEPARTED.getValue()));
        return update > 0 ? R.ok() : R.fail();
    }

    /**
     * 取消接诊
     *
     * @param encounterId 就诊id
     * @return 结果
     */
    @Override
    public R<?> cancelEncounter(Long encounterId) {
        //1.判断是否已经产生业务，如医生已经开有病历、处方、诊断、检验检查或相关项目已收费、执行等，
        //如果有则提示:需要医生删除、作废、退费才能【取消接诊】。
        //1.1病历
        Object emrDetailResult = iDoctorStationEmrAppService.getEmrDetail(encounterId).getData();

        //1.2诊断
        Object diagnosisResult = iDoctorStationDiagnosisAppService.getEncounterDiagnosis(encounterId).getData();

        //1.3处方
        Object adviceResult = iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId).getData();

        //1.4中医诊断、处方
        Map<?,?> tcmDiagnosisResult = (Map<?,?>) iDoctorStationChineseMedicalAppService.getTcmEncounterDiagnosis(encounterId).getData();
        Object symptom = tcmDiagnosisResult.get("symptom");
        Object illness = tcmDiagnosisResult.get("illness");
        Object tcmPrescriptionResult = iDoctorStationChineseMedicalAppService.getTcmRequestBaseInfo(encounterId).getData();

        boolean isEmpty = ObjectUtil.isAllEmpty(emrDetailResult, diagnosisResult, adviceResult, symptom,illness, tcmPrescriptionResult);

        if (!isEmpty) {
            return R.fail();
        }

        //2.取消接诊，患者重新回到患者队列待诊中
        int update = encounterMapper.update(null,
                new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
                        .set(Encounter::getStatusEnum, EncounterStatus.PLANNED.getValue())
                        .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.TRIAGED.getValue()));
        return update > 0 ? R.ok() : R.fail();
    }

    /**
     * 查询处方号列表信息
     *
     * @param prescriptionInfoBaseDto 处方dto
     * @param searchKey 模糊查询关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 处方号列表信息
     */
    @Override
    public IPage<PrescriptionInfoBaseDto> getPrescriptionPageInfo(PrescriptionInfoBaseDto prescriptionInfoBaseDto,
        String searchKey, Integer pageNo, Integer pageSize) {
        // 构建查询条件
        QueryWrapper<PrescriptionInfoBaseDto> queryWrapper = HisQueryUtils.buildQueryWrapper(prescriptionInfoBaseDto,
            searchKey, new HashSet<>(Arrays.asList("prescription_no", "patient_name", "practitioner_name")), null);
        IPage<PrescriptionInfoBaseDto> prescriptionPageInfo =
            doctorStationMainAppMapper.getPrescriptionPageInfo(new Page<>(pageNo, pageSize), queryWrapper);
        List<PrescriptionInfoBaseDto> PrescriptionInfo = prescriptionPageInfo.getRecords();
        // 本次就诊的处方信息
        List<PrescriptionInfoDetailDto> prescriptionDetailInfo =
            doctorStationMainAppMapper.getPrescriptionDetailInfo(null, prescriptionInfoBaseDto.getEncounterId());
        for (PrescriptionInfoBaseDto infoBaseDto : PrescriptionInfo) {
            // 性别
            infoBaseDto.setGenderEnum_enumText(
                EnumUtils.getInfoByValue(AdministrativeGender.class, infoBaseDto.getGenderEnum()));
            // 计算年龄
            infoBaseDto
                .setAge(infoBaseDto.getBirthDate() != null ? AgeCalculatorUtil.getAge(infoBaseDto.getBirthDate()) : "");
            // 处方单详情
            List<PrescriptionInfoDetailDto> prescriptionInfoDetailList = prescriptionDetailInfo.stream()
                .filter(e -> infoBaseDto.getPrescriptionNo().equals(e.getPrescriptionNo()))
                .collect(Collectors.toList());
            infoBaseDto.setPrescriptionInfoDetailList(prescriptionInfoDetailList);
        }
        return prescriptionPageInfo;
    }

    /**
     * 查询处方详情
     *
     * @param prescriptionNo 处方号
     * @return 处方详情
     */
    @Override
    public List<PrescriptionInfoDetailDto> getPrescriptionDetailInfo(String prescriptionNo) {
        List<PrescriptionInfoDetailDto> prescriptionDetailInfo =
            doctorStationMainAppMapper.getPrescriptionDetailInfo(prescriptionNo, null);
        for (PrescriptionInfoDetailDto prescriptionInfoDetailDto : prescriptionDetailInfo) {
            // 请求状态
            prescriptionInfoDetailDto.setStatusEnum_enumText(
                EnumUtils.getInfoByValue(RequestStatus.class, prescriptionInfoDetailDto.getStatusEnum()));
            // 收费状态
            prescriptionInfoDetailDto.setChargeStatus_enumText(
                EnumUtils.getInfoByValue(ChargeItemStatus.class, prescriptionInfoDetailDto.getChargeStatus()));
        }
        return prescriptionDetailInfo;
    }

}
