package com.eitc.patient.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eitc.common.utils.bean.BeanUtils;
import com.eitc.patient.domain.MedicalRecord;
import com.eitc.patient.domain.MedicalRecordDetails;
import com.eitc.patient.domain.PatientAppointment;
import com.eitc.patient.dto.MedicalRecordHistoryDto;
import com.eitc.patient.dto.MedicalRecordListDto;
import com.eitc.patient.enums.MedicalRecordStatusEnum;
import com.eitc.patient.enums.PatientAppointmentStatusEnum;
import com.eitc.patient.mapper.MedicalRecordMapper;
import com.eitc.patient.param.MedicalRecordSaveParam;
import com.eitc.patient.service.ICollectCostPatientsService;
import com.eitc.patient.service.IMedicalHistoryService;
import com.eitc.patient.service.IMedicalRecordDetailsService;
import com.eitc.patient.service.IMedicalRecordService;
import com.eitc.patient.service.IPatientAppointmentService;
import com.eitc.patient.vo.MedicalRecordToothVO;
import com.eitc.system.utils.UserCacheUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * MedicalRecordServiceImpl
 *
 * @author mtx
 * @date: 2024/05/17 15:39
 */
@Service
public class MedicalRecordServiceImpl extends ServiceImpl<MedicalRecordMapper, MedicalRecord> implements IMedicalRecordService {

    @Resource
    private IMedicalHistoryService medicalHistoryService;
    @Resource
    private IMedicalRecordDetailsService medicalRecordDetailsService;
    @Resource
    private IPatientAppointmentService patientAppointmentService;
    @Resource
    private ICollectCostPatientsService collectCostPatientsService;

    /**
     * 保存或编辑病历信息。
     *
     * @param param 包含病历及相关信息的参数对象。
     * @author mtx
     * @date 2024/5/22 10:00
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void addOrEdit(MedicalRecordSaveParam param) {
        // 初始化病历对象并设置基本信息，保存病历信息
        MedicalRecord medicalRecord = saveMedicalRecordInfo(param);

        // 保存个人录入的病史信息到病历记录中
        medicalHistoryService.saveMedicalHistoryByHistoryType(param, medicalRecord.getId());

        // 初始化标志位和计数器，用于后续处理
        AtomicBoolean flag = new AtomicBoolean(true);
        List<MedicalRecordDetails> recordDetailsList = new ArrayList<>();

        List<MedicalRecordToothVO> dataList = param.getToothList();
        if (CollectionUtils.isNotEmpty(dataList)) {
            // 遍历病历详情列表，处理每条详情信息
            dataList.forEach(medicalRecordToothVO -> {
                MedicalRecordDetails recordDetails = new MedicalRecordDetails();
                BeanUtils.copyProperties(medicalRecordToothVO, recordDetails);
                recordDetails.setMedicalRecordId(medicalRecord.getId());
                recordDetailsList.add(recordDetails);
            });
        }

        // 修改预约状态
        if (StringUtils.isNotBlank(param.getAppointmentId())) {
            PatientAppointment appointment = new PatientAppointment();
            appointment.setId(param.getAppointmentId());
            appointment.setMedicalRecordId(medicalRecord.getId());
            appointment.setAppointmentStatus(flag.get() ? PatientAppointmentStatusEnum.TREATMENT_COMPLETED.getCode() : PatientAppointmentStatusEnum.IN_TREATMENT.getCode());
            patientAppointmentService.updateById(appointment);
        }

        // 删除旧的病历详情信息，然后保存新的病历详情信息
        medicalRecordDetailsService.remove(Wrappers.<MedicalRecordDetails>lambdaQuery().eq(MedicalRecordDetails::getMedicalRecordId, medicalRecord.getId()));
        medicalRecordDetailsService.saveBatch(recordDetailsList);

        // 保存收费信息
        BigDecimal bigDecimal = collectCostPatientsService.saveCollectCostPatientsToMedicalRecord(recordDetailsList, medicalRecord.getPatientId());
        // 根据病历ID更新病历状态
        MedicalRecord mr = new MedicalRecord();
        mr.setStatus(flag.get() ? MedicalRecordStatusEnum.ALREADY_COMPLETE.getCode() : MedicalRecordStatusEnum.WAIT_COMPLETE.getCode());
        mr.setId(medicalRecord.getId());
        mr.setCost(bigDecimal);
        this.updateById(mr);
    }


    /**
     * 初始化病历对象并设置基本信息，保存病历信息
     *
     * @param param 参数
     * @return 返回
     */
    @Transactional(rollbackFor = {Exception.class})
    public MedicalRecord saveMedicalRecordInfo(MedicalRecordSaveParam param) {
        MedicalRecord medicalRecord = new MedicalRecord();
        medicalRecord.setPatientId(param.getPatientId());
        medicalRecord.setVisitType(param.getVisitType());
        medicalRecord.setAttendingDoctorId(param.getAttendingDoctorId());
        medicalRecord.setAttendingDoctorName(UserCacheUtil.getSysUserById(param.getAttendingDoctorId()).getNickName());
        medicalRecord.setOutpatientService(UserCacheUtil.getClinicName());
        medicalRecord.setDepartment(UserCacheUtil.getSysDeptByUserId(param.getAttendingDoctorId()).getDeptName());
        medicalRecord.setCost(BigDecimal.ZERO);

        medicalRecord.setChiefComplaintContent(param.getChiefComplaintContent());
        medicalRecord.setPresentIllnessContent(param.getPresentIllnessContent());
        medicalRecord.setInspectContent(param.getInspectContent());
        medicalRecord.setTreatmentPlanningContent(param.getTreatmentPlanningContent());
        medicalRecord.setDisposeContent(param.getDisposeContent());
        medicalRecord.setNoteContent(param.getNoteContent());
        medicalRecord.setDiagnosisContent(param.getDiagnosisContent());

        medicalRecord.setSaveStatus(param.getSaveStatus());

        if (Objects.nonNull(param.getId())) {
            medicalRecord.setId(param.getId());
        }
        this.saveOrUpdate(medicalRecord);
        return medicalRecord;
    }

    /**
     * 病历列表
     *
     * @param searchParam 病历信息
     * @return 病历列表
     * @author mtx
     * @date: 2024/5/23 9:17
     */
    @Override
    public List<MedicalRecordListDto> medicalRecordList(String searchParam) {
        return this.getBaseMapper().medicalRecordList(searchParam);
    }

    /**
     * 统计诊断分类
     *
     * @return 统计结果
     * @author mtx
     * @date: 2024/6/5 9:10
     */
    @Override
    public List<Map<String, String>> countByDiagnosisTypeName() {
        return this.baseMapper.countByDiagnosisTypeName();
    }

    /**
     * 根据牙齿位置检查访问类型
     *
     * @return 返回访问类型，具体类型根据业务逻辑确定
     */
    @Override
    public List<MedicalRecord> findListByToothPosition(MedicalRecordHistoryDto dto) {
        if (CollectionUtils.isEmpty(dto.getToothPositionList())) {
            return new ArrayList<>();
        }
        if (StringUtils.isBlank(dto.getPatientId())) {
            throw new IllegalArgumentException("患者ID不能为空");
        }
        return this.baseMapper.findListByToothPosition(dto);
    }

}
