package com.eitc.patient.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eitc.common.annotation.Log;
import com.eitc.common.core.controller.BaseController;
import com.eitc.common.core.domain.AjaxResult;
import com.eitc.common.core.domain.entity.SysUser;
import com.eitc.common.enums.BusinessType;
import com.eitc.common.utils.bean.BeanUtils;
import com.eitc.patient.domain.MedicalHistory;
import com.eitc.patient.domain.Patient;
import com.eitc.patient.domain.PatientAppointment;
import com.eitc.patient.enums.MedicalHistoryDiseaseSourceEnum;
import com.eitc.patient.enums.MedicalHistoryDiseaseTypeEnum;
import com.eitc.patient.service.IMedicalHistoryService;
import com.eitc.patient.service.IPatientAppointmentService;
import com.eitc.patient.service.IPatientService;
import com.eitc.patient.utils.PatientUtil;
import com.eitc.patient.vo.PatientVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * PatientController
 *
 * @author mtx
 * @date: 2024/05/17 15:52
 */
@Api(tags = "患者")
@RestController
@RequestMapping("/patient/patient")
public class PatientController extends BaseController {

    @Resource
    private IPatientService patientService;
    @Resource
    private IMedicalHistoryService medicalHistoryService;
    @Resource
    private IPatientAppointmentService patientAppointmentService;

    @GetMapping("/listByName")
    @ApiOperation("查询患者")
    public AjaxResult listByName(@RequestParam(name = "patientName", required = false) String patientName) {
        LambdaQueryWrapper<Patient> eq = Wrappers.<Patient>lambdaQuery()
                .like(Patient::getPatientName, patientName)
                .orderByDesc(Patient::getCreateDate);
        List<Patient> list = patientService.list(eq);
        return success(list);
    }

    /**
     * 查询患者
     */
    @GetMapping("/list")
    @ApiOperation("查询患者")
    public AjaxResult list(@RequestParam(name = "searchParam", required = false) String searchParam) {
        LambdaQueryWrapper<Patient> eq = Wrappers.<Patient>lambdaQuery()
                .like(StringUtils.isNotBlank(searchParam), Patient::getPatientPhone, searchParam).or()
                .like(StringUtils.isNotBlank(searchParam), Patient::getLinkPhone, searchParam).or()
                .like(StringUtils.isNotBlank(searchParam), Patient::getPatientName, searchParam).or()
                .like(StringUtils.isNotBlank(searchParam), Patient::getIdentificationCard, searchParam)
                .orderByDesc(Patient::getCreateDate);
        List<Patient> list = patientService.list(eq);
        if (CollectionUtils.isEmpty(list)) {
            return success(new ArrayList<>());
        }
        List<PatientVO> listVO = new ArrayList<>();
        List<SysUser> sysUserList = PatientUtil.findUserListByLoginUser();
        for (Patient li : list) {
            PatientVO vo = getPatientVO(li);
            String visitingPhysicianSet = vo.getVisitingPhysicianSet();
            long count = 0L;
            if (StringUtils.isNotBlank(visitingPhysicianSet)) {
                count = sysUserList.stream().filter(user -> visitingPhysicianSet.contains(user.getNickName())).count();
            }
            if (CollectionUtils.isEmpty(sysUserList) || count > 0) {
                listVO.add(vo);
            }
        }
        return success(listVO);
    }

    /**
     * 根据Patient实体类对象，获取对应的PatientVO（患者信息视图对象）。
     * 该方法通过拷贝Patient的基本属性到PatientVO中，并进一步查询该患者的预约信息和病史信息，
     * 以完善PatientVO中的访问时间、就诊医生、预约人等信息，以及过敏史、既往史、家族史等详细病史信息。
     *
     * @param li Patient实体类对象，代表一个患者的信息。
     * @return 返回填充了预约信息和病史信息的PatientVO对象。
     */
    private PatientVO getPatientVO(Patient li) {
        // 创建一个PatientVO对象，用于存储患者的信息。
        PatientVO vo = new PatientVO();
        // 使用BeanUtils工具类，将Patient对象的属性值复制到PatientVO对象中。
        BeanUtils.copyProperties(li, vo);

        // 查询该患者的所有预约信息，并按照创建日期降序排列。
        List<PatientAppointment> list = patientAppointmentService.list(Wrappers.<PatientAppointment>lambdaQuery()
                .eq(PatientAppointment::getAppointmentPersonId, li.getId())
                .orderByDesc(PatientAppointment::getCreateDate));
        // 如果查询结果不为空，则处理第一条预约信息，用于设置访问时间和就诊医生等信息。
        if (CollectionUtils.isNotEmpty(list)) {
            Optional<PatientAppointment> first = list.stream().findFirst();
            if (first.isPresent()) {
                PatientAppointment one = first.get();
                // 设置患者的访问时间。
                vo.setVisitTime(one.getAppointmentStartTime());
                // 设置患者的就诊医生。
                vo.setVisitingPhysician(one.getAttendingDoctor());
                // 设置预约人信息。
                vo.setAppointmentPerson(one.getRegisterUser());
            }
            vo.setVisitingPhysicianSet(list.stream().map(PatientAppointment::getAttendingDoctor)
                    .distinct().collect(Collectors.joining(",")));
        }

        // 查询该患者的全部病史信息，包括过敏史、既往史、家族史等。
        List<MedicalHistory> histories = medicalHistoryService.list(Wrappers.<MedicalHistory>lambdaQuery()
                .eq(MedicalHistory::getDiseaseSource, MedicalHistoryDiseaseSourceEnum.PATIENT.getCode())
                .eq(MedicalHistory::getPatientId, li.getId()));
        // 如果查询结果不为空，则分别处理过敏史、既往史、家族史信息，并设置到PatientVO中。
        if (CollectionUtils.isNotEmpty(histories)) {
            // 设置患者的过敏史信息，将所有过敏史内容通过逗号连接。
            vo.setAllergyHistory(
                    histories.stream()
                            .filter(entry -> MedicalHistoryDiseaseTypeEnum.ALLERGY_HISTORY.getCode().equals(entry.getDiseaseType()))
                            .map(MedicalHistory::getDiseaseContent)
                            .collect(Collectors.joining(","))
            );
            // 设置患者的既往史信息，将所有既往史内容通过逗号连接。
            vo.setPastHistory(
                    histories.stream()
                            .filter(entry -> MedicalHistoryDiseaseTypeEnum.PAST_HISTORY.getCode().equals(entry.getDiseaseType()))
                            .map(MedicalHistory::getDiseaseContent)
                            .collect(Collectors.joining(","))
            );
            // 设置患者的家族史信息，将所有家族史内容通过逗号连接。
            vo.setFamilyHistory(
                    histories.stream()
                            .filter(entry -> MedicalHistoryDiseaseTypeEnum.FAMILY_HISTORY.getCode().equals(entry.getDiseaseType()))
                            .map(MedicalHistory::getDiseaseContent)
                            .collect(Collectors.joining(","))
            );
        }
        // 返回填充了预约信息和病史信息的PatientVO对象。
        return vo;
    }


    /**
     * 获取患者详细信息
     */
    @GetMapping(value = "/detail")
    @ApiOperation("获取患者详细信息")
    public AjaxResult detail(String id) {
        Patient patient = patientService.getById(id);
        return success(getPatientVO(patient));
    }

    /**
     * 新增患者
     */
    @Log(title = "新增患者", businessType = BusinessType.INSERT)
    @PostMapping
    @ApiOperation("新增患者")
    public AjaxResult add(@Valid @RequestBody PatientVO vo) {
        patientService.addOrEdit(vo);
        return success();
    }

    /**
     * 修改患者
     */
    @Log(title = "修改患者", businessType = BusinessType.UPDATE)
    @PutMapping
    @ApiOperation("修改患者")
    public AjaxResult edit(@Valid @RequestBody PatientVO vo) {
        if (StringUtils.isEmpty(vo.getId())) {
            return error();
        }
        patientService.addOrEdit(vo);
        return success();
    }

    /**
     * 删除患者
     */
    @Log(title = "删除患者", businessType = BusinessType.DELETE)
    @DeleteMapping("/remove")
    @ApiOperation("删除患者")
    public AjaxResult remove(String ids) {
        List<String> idList = Arrays.asList(ids.split(","));
        return toAjax(patientService.delete(idList));
    }

}
