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

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

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

import com.openhis.common.enums.EncounterActivityStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.Practitioner;
import com.openhis.administration.service.IPractitionerService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.AdministrativeGender;
import com.openhis.common.enums.EncounterClass;
import com.openhis.common.enums.LocationForm;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.document.domain.Emr;
import com.openhis.document.domain.EmrTemplate;
import com.openhis.document.domain.VitalSigns;
import com.openhis.document.service.IEmrService;
import com.openhis.document.service.IEmrTemplateService;
import com.openhis.document.service.IVitalSignsService;
import com.openhis.web.inpatientmanage.appservice.INursingRecordAppService;
import com.openhis.web.inpatientmanage.dto.*;
import com.openhis.web.inpatientmanage.mapper.NursingRecordAppMapper;

/**
 * 护理记录单 实现类
 *
 * @author gyy
 * @since 2025/05/30
 */
@Service
public class NursingRecordAppServiceImpl implements INursingRecordAppService {

    @Resource
    private NursingRecordAppMapper nursingRecordAppMapper;

    @Resource
    private IEmrService emrService;

    @Resource
    private IVitalSignsService vitalSignsService;

    @Resource
    private IPractitionerService practitionerService;

    @Resource
    private IEmrTemplateService emrTemplateService;

    /**
     * 获取住院患者信息 分页显示
     *
     * @param nursingSearchParam 查询参数
     * @param searchKey 模糊查询
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 患者信息
     */
    @Override
    public R<?> getPatientInfoPage(NursingSearchParam nursingSearchParam, String searchKey, Integer pageNo,
        Integer pageSize, HttpServletRequest request) {

        // 构建查询条件
        QueryWrapper<NursingSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(nursingSearchParam, searchKey,
            new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientName, CommonConstants.FieldName.PatientBusNo)),
            request);

        // 分页查询,查询患者信息
        IPage<NursingPageDto> NursingInfoPage = nursingRecordAppMapper.getPatientPage(new Page<>(pageNo, pageSize),
            EncounterClass.IMP.getValue(), LocationForm.BED.getValue(), LocationForm.WARD.getValue(),
            EncounterActivityStatus.ACTIVE.getValue(), queryWrapper);

        NursingInfoPage.getRecords().forEach(e -> {
            // 性别枚举类回显赋值
            e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum()));
            // 计算年龄
            e.setAgeString(AgeCalculatorUtil.getAge(e.getBirthDate()));
        });

        // 返回【住院患者信息列表DTO】分页
        return R.ok(NursingInfoPage);
    }

    /**
     * 获取患者护理记录单信息 分页显示
     *
     * @param nursingSearchParam 查询参数
     * @param searchKey 模糊查询
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 患者护理记录单信息
     */
    @Override
    public R<?> getNursingPatientPage(NursingSearchParam nursingSearchParam, String searchKey, Integer pageNo,
        Integer pageSize, HttpServletRequest request) {

        // 构建查询条件
        QueryWrapper<NursingSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(nursingSearchParam, searchKey,
            new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientId)), request);

        // 分页查询,查询患者护理记录单信息
        IPage<NursingDetailDto> NursingPatientPage = nursingRecordAppMapper.getNursingPatientPage(
            new Page<>(pageNo, pageSize), EncounterClass.IMP.getValue(), LocationForm.BED.getValue(),
            LocationForm.WARD.getValue(), EncounterActivityStatus.ACTIVE.getValue(), queryWrapper);

        NursingPatientPage.getRecords().forEach(e -> {
            // 性别枚举类回显赋值
            e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum()));
            // 计算年龄
            e.setAgeString(AgeCalculatorUtil.getAge(e.getBirthDate()));
        });

        // 返回【住院患者护理记录单信息列表DTO】分页
        return R.ok(NursingPatientPage);
    }

    /**
     * 保存护理记录单
     *
     * @param nursingRecordDto 入参
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> saveRecord(NursingRecordDto nursingRecordDto) {
        // 取得记录人员id
        Long recorderId = SecurityUtils.getLoginUser().getPractitionerId();

        Emr emr = new Emr();
        // 病历信息
        emr.setEncounterId(nursingRecordDto.getEncounterId()).setPatientId(nursingRecordDto.getPatientId())
            .setRecordId(recorderId).setRecordTime(nursingRecordDto.getRecordingTime()).setClassEnum(1)
            .setContextJson(nursingRecordDto.getContextJson());

        // 病历（记录单）保存
        boolean saveSuccess = emrService.save(emr);
        // 是否同步到体征表
        if (nursingRecordDto.getVitalSignsSyncFlag()) {
            this.vitalSigns(nursingRecordDto, recorderId);
        }

        if (saveSuccess) {
            return R.ok(nursingRecordDto,
                MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"护理记录单"}));
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
    }

    /**
     * 编辑护理记录单
     *
     * @param nursingRecordDto 入参
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> updateRecord(NursingRecordDto nursingRecordDto) {
        // 取得记录人员id
        Long recordId = SecurityUtils.getLoginUser().getPractitionerId();

        // 病历（记录单）保存
        Emr emr = new Emr();
        emr.setId(nursingRecordDto.getRecordId()).setEncounterId(nursingRecordDto.getEncounterId())
            .setPatientId(nursingRecordDto.getPatientId()).setRecordId(recordId)
            .setRecordTime(nursingRecordDto.getRecordingTime()).setClassEnum(1)
            .setContextJson(nursingRecordDto.getContextJson());
        boolean updateSuccess = emrService.updateById(emr);

        // 是否同步到体征表
        if (nursingRecordDto.getVitalSignsSyncFlag()) {
            this.vitalSigns(nursingRecordDto, recordId);
        } else {
            // 编辑时不同步到体征单的场合，删除体征单之前的记录
            this.deleteVitalSigns(nursingRecordDto);
        }

        if (updateSuccess) {
            return R.ok(nursingRecordDto,
                MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"护理记录单"}));
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
    }

    /**
     * 编辑时不同步到体征单的场合，删除体征单之前的记录
     *
     * @param nursingRecordDto
     * @return 结果
     */
    private void deleteVitalSigns(NursingRecordDto nursingRecordDto) {
        // 查询在体征表中是否存在数据
        LambdaQueryWrapper<VitalSigns> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VitalSigns::getEncounterId, nursingRecordDto.getEncounterId())
            .eq(VitalSigns::getPatientId, nursingRecordDto.getPatientId())
            .eq(VitalSigns::getTimePoint, nursingRecordDto.getRecordingTime());
        List<VitalSigns> vitalSignsList = vitalSignsService.list(queryWrapper);
        // 存在的场合删除记录
        if (vitalSignsList.size() != 0) {
            // 获取生命体征管理ID的List
            List<Long> vitalSignsIdList = vitalSignsList.stream().map(VitalSigns::getId).collect(Collectors.toList());
            // 删除记录
            vitalSignsService.removeByIds(vitalSignsIdList);
        }
    }

    /**
     * 生命体征转换，同步到体征单
     *
     * @param nursingRecordDto
     * @return 结果
     */
    private void vitalSigns(NursingRecordDto nursingRecordDto, long recorderId) {

        // 取得记录人员姓名
        Practitioner practitioner = practitionerService.getById(recorderId);
        // 体征转换
        NursingVitalSignsDto nursingVitalSigns =
            JSONObject.parseObject(nursingRecordDto.getContextJson(), NursingVitalSignsDto.class);
        // 体温
        String tw = nursingVitalSigns.getTw();
        // 脉搏
        String mb = nursingVitalSigns.getMb();
        // 呼吸
        String hx = nursingVitalSigns.getHx();

        if (tw != null && tw.length() > 0) {
            // 体征表保存或更新（体温）
            VitalSigns vitalSigns = new VitalSigns();
            vitalSigns.setPatientId(nursingRecordDto.getPatientId()).setEncounterId(nursingRecordDto.getEncounterId())
                .setRecordingDate(nursingRecordDto.getRecordingTime()).setTimePoint(nursingRecordDto.getRecordingTime())
                .setRecorder(practitioner.getName()).setVitalSignsCode("007").setVitalSignsValues(tw);
            vitalSignsService.saveOrUpdateVitalSigns(vitalSigns);
        } else {
            // 体温未录入时，体征表之前存储的体温数据删除
            VitalSigns vitalSigns = new VitalSigns();
            vitalSigns.setEncounterId(nursingRecordDto.getEncounterId())
                .setTimePoint(nursingRecordDto.getRecordingTime()).setVitalSignsCode("007");
            vitalSignsService.deleteVitalSigns(vitalSigns);
        }
        if (mb != null && mb.length() > 0) {
            // 体征表保存或更新（脉搏）
            VitalSigns vitalSigns = new VitalSigns();
            vitalSigns.setPatientId(nursingRecordDto.getPatientId()).setEncounterId(nursingRecordDto.getEncounterId())
                .setRecordingDate(nursingRecordDto.getRecordingTime()).setTimePoint(nursingRecordDto.getRecordingTime())
                .setRecorder(practitioner.getName()).setVitalSignsCode("003").setVitalSignsValues(mb);
            vitalSignsService.saveOrUpdateVitalSigns(vitalSigns);
        } else {
            // 脉搏未录入时，体征表之前存储的脉搏数据删除
            VitalSigns vitalSigns = new VitalSigns();
            vitalSigns.setEncounterId(nursingRecordDto.getEncounterId())
                .setTimePoint(nursingRecordDto.getRecordingTime()).setVitalSignsCode("003");
            vitalSignsService.deleteVitalSigns(vitalSigns);
        }
        if (hx != null && hx.length() > 0) {
            // 体征表保存或更新（呼吸）
            VitalSigns vitalSigns = new VitalSigns();
            vitalSigns.setPatientId(nursingRecordDto.getPatientId()).setEncounterId(nursingRecordDto.getEncounterId())
                .setRecordingDate(nursingRecordDto.getRecordingTime()).setTimePoint(nursingRecordDto.getRecordingTime())
                .setRecorder(practitioner.getName()).setVitalSignsCode("006").setVitalSignsValues(hx);
            vitalSignsService.saveOrUpdateVitalSigns(vitalSigns);
        } else {
            // 呼吸未录入时，体征表之前存储的呼吸数据删除
            VitalSigns vitalSigns = new VitalSigns();
            vitalSigns.setEncounterId(nursingRecordDto.getEncounterId())
                .setTimePoint(nursingRecordDto.getRecordingTime()).setVitalSignsCode("006");
            vitalSignsService.deleteVitalSigns(vitalSigns);
        }
    }

    /**
     * 删除护理记录单
     *
     * @param recordList 记录单list
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> delRecord(List<NursingRecordDto> recordList) {

        for (NursingRecordDto record : recordList) {
            // 病历（记录单）删除
            emrService.removeById(record.getRecordId());
            // 查询在体征表中是否存在数据
            LambdaQueryWrapper<VitalSigns> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(VitalSigns::getEncounterId, record.getEncounterId())
                .eq(VitalSigns::getPatientId, record.getPatientId())
                .eq(VitalSigns::getTimePoint, record.getRecordingTime());
            List<VitalSigns> vitalSignsList = vitalSignsService.list(queryWrapper);
            // 存在的场合删除记录
            if (vitalSignsList.size() != 0) {
                // 获取生命体征管理ID的List
                List<Long> vitalSignsIdList =
                    vitalSignsList.stream().map(VitalSigns::getId).collect(Collectors.toList());
                // 删除记录
                vitalSignsService.removeByIds(vitalSignsIdList);
            }
        }
        return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 获取电子病历模板列表 分页显示
     *
     * @param nursingSearchParam 查询参数
     * @param searchKey 模糊查询
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 电子病历模板信息
     */
    @Override
    public R<?> getEmrTemplate(NursingSearchParam nursingSearchParam, String searchKey, Integer pageNo,
        Integer pageSize, HttpServletRequest request) {

        // 构建查询条件
        QueryWrapper<NursingSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(nursingSearchParam, searchKey,
            new HashSet<>(Arrays.asList("template_name")), request);

        // 分页查询,查询电子病历模板信息
        IPage<NursingEmrTemplateDto> emrTemplatePage =
            nursingRecordAppMapper.getEmrTemplate(new Page<>(pageNo, pageSize), "1", queryWrapper);

        // 返回【电子病历模板】分页
        return R.ok(emrTemplatePage);
    }

    /**
     * 保存病历模板
     *
     * @param emrTemplateDto 病历模板信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> saveEmrTemplate(NursingEmrTemplateDto emrTemplateDto) {

        EmrTemplate emrTemplate = new EmrTemplate();
        // 保存病历模板信息
        emrTemplate.setTemplateName(emrTemplateDto.getTemplateName()).setTemplateTypeCode("1")
            .setUseScopeCode(emrTemplateDto.getUseScopeCode()).setUserId(emrTemplateDto.getUserId())
            .setContextJson(emrTemplateDto.getContextJson());

        return emrTemplateService.save(emrTemplate) ? R.ok() : R.fail();
    }

    /**
     * 删除病历模板
     *
     * @param idList 模板id
     * @return 操作结果
     */
    @Override
    public R<?> deleteEmrTemplate(List<Long> idList) {
        return emrTemplateService.removeByIds(idList) ? R.ok() : R.fail();
    }

    /**
     * 编辑病历模板
     *
     * @param emrTemplateDto 病历模板信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> updateEmrTemplate(NursingEmrTemplateDto emrTemplateDto) {

        EmrTemplate emrTemplate = new EmrTemplate();
        // 病历模板信息更新
        emrTemplate.setId(emrTemplateDto.getId()).setTemplateName(emrTemplateDto.getTemplateName())
            .setTemplateTypeCode("1").setUseScopeCode(emrTemplateDto.getUseScopeCode())
            .setUserId(emrTemplateDto.getUserId()).setContextJson(emrTemplateDto.getContextJson());

        return emrTemplateService.updateById(emrTemplate) ? R.ok() : R.fail();
    }

}
