package com.xinelu.applet.service.nursepersonapplogin.impl;


import com.xinelu.applet.dto.nursepersonapplogin.OrderFallbackDTO;
import com.xinelu.applet.mapper.nursepersonapplogin.NursePersonAppLoginMapper;
import com.xinelu.applet.service.nursepersonapplogin.INursePersonAppLoginService;
import com.xinelu.applet.vo.nursepersonapplogin.*;
import com.xinelu.common.config.XinELuConfig;
import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.enums.OrderStatusEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.AgeUtil;
import com.xinelu.common.utils.file.FileUploadUtils;
import com.xinelu.common.utils.file.MimeTypeUtils;
import com.xinelu.common.utils.regex.RegexUtil;
import com.xinelu.common.utils.sign.Md5Utils;
import com.xinelu.manage.domain.appointmentorderdetails.AppointmentOrderDetails;
import com.xinelu.manage.domain.nursestationperson.NurseStationPerson;
import com.xinelu.manage.domain.nursestationpersonrevenue.NurseStationPersonRevenue;
import com.xinelu.manage.domain.patientdiseaseinfo.PatientDiseaseInfo;
import com.xinelu.manage.mapper.appointmentorderdetails.AppointmentOrderDetailsMapper;
import com.xinelu.manage.mapper.nursestation.NurseStationMapper;
import com.xinelu.manage.mapper.nursestationperson.NurseStationPersonMapper;
import com.xinelu.manage.mapper.nursestationpersonrevenue.NurseStationPersonRevenueMapper;
import com.xinelu.manage.mapper.patientdiseaseinfo.PatientDiseaseInfoMapper;
import com.xinelu.manage.vo.appointmentorder.AppointmentOrderRecordVO;
import com.xinelu.manage.vo.appointmentorder.AppointmentReceivingOrderVO;
import com.xinelu.manage.vo.nursestation.NurseStationSysUserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description 护理人员APP登录注册业务层实现类
 * @Author ZH
 * @Date 2022-10-28
 */
@Service
@Slf4j
public class NursePersonAppLoginServiceImpl implements INursePersonAppLoginService {
    @Resource
    private NursePersonAppLoginMapper nursePersonAppLoginMapper;
    @Resource
    private AppointmentOrderDetailsMapper appointmentOrderDetailsMapper;
    @Resource
    private RegexUtil regexUtil;
    @Resource
    private NurseStationMapper nurseStationMapper;
    @Resource
    private NursePersonAppLoginServiceImpl nursePersonAppLoginService;
    @Resource
    private NurseStationPersonMapper nurseStationPersonMapper;
    @Resource
    private XinELuConfig xinYiLuConfig;
    @Resource
    private NurseStationPersonRevenueMapper nurseStationPersonRevenueMapper;
    @Resource
    private PatientDiseaseInfoMapper patientDiseaseInfoMapper;

    /**
     * 工单首页查询已完成以及未完成数量
     *
     * @param nurseStationPersonId 护理员id
     * @return int
     **/
    @Override
    public AjaxResult selectOrderByNursePersonCount(Long nurseStationPersonId) {
        OrderByNursePersonVO orderByNursePersonVO = new OrderByNursePersonVO();
        if (Objects.isNull(nurseStationPersonId)) {
            orderByNursePersonVO.setCompleteCount(0L);
            orderByNursePersonVO.setNotFinishCount(0L);
            return AjaxResult.success(orderByNursePersonVO);
        }
        List<String> orderStatusList = Arrays.asList(OrderStatusEnum.NOT_FINISH.getInfo(), OrderStatusEnum.WAIT_RECEIVE.getInfo(), OrderStatusEnum.COMPLETE.getInfo(), OrderStatusEnum.EVALUATED.getInfo());
        List<OrderByNursePersonVO> orderByNursePersonList = nursePersonAppLoginMapper.selectOrderByNursePersonCount(nurseStationPersonId, orderStatusList);
        long completeCount = orderByNursePersonList.stream().filter(Objects::nonNull).filter(order -> (StringUtils.isNotBlank(order.getOrderStatus())) && order.getOrderStatus().equals(OrderStatusEnum.COMPLETE.getInfo()) || order.getOrderStatus().equals(OrderStatusEnum.EVALUATED.getInfo())).count();
        long notFinishCount = orderByNursePersonList.stream().filter(Objects::nonNull).filter(order -> (StringUtils.isNotBlank(order.getOrderStatus())) && order.getOrderStatus().equals(OrderStatusEnum.NOT_FINISH.getInfo()) || order.getOrderStatus().equals(OrderStatusEnum.WAIT_RECEIVE.getInfo())).count();
        orderByNursePersonVO.setCompleteCount(completeCount);
        orderByNursePersonVO.setNotFinishCount(notFinishCount);
        return AjaxResult.success(orderByNursePersonVO);
    }

    /**
     * 服务人员我的任务界面 查询服务订单
     *
     * @param orderAndItem 预约订单信息
     * @return 结果
     */
    @Override
    public List<OrderAndItemVO> selectAppointmentOrder(OrderAndItemVO orderAndItem) {
        List<OrderAndItemVO> appointmentOrderDetails = new ArrayList<>();
        if (Objects.isNull(orderAndItem) || Objects.isNull(orderAndItem.getNursePersonId())) {
            return appointmentOrderDetails;
        }
        List<String> orderStatusList;
        //处理全部订单状态筛选条件
        if (StringUtils.isBlank(orderAndItem.getOrderStatus())) {
            orderStatusList = Arrays.asList(OrderStatusEnum.NOT_FINISH.getInfo(), OrderStatusEnum.WAIT_RECEIVE.getInfo(), OrderStatusEnum.COMPLETE.getInfo(), OrderStatusEnum.EVALUATED.getInfo());
            orderAndItem.setOrderStatusList(orderStatusList);
        }
        //处理当前订单状态筛选条件
        if (StringUtils.isNotBlank(orderAndItem.getOrderStatus()) && StringUtils.equals(OrderStatusEnum.NOT_FINISH.getInfo(), orderAndItem.getOrderStatus())) {
            orderStatusList = Arrays.asList(OrderStatusEnum.NOT_FINISH.getInfo(), OrderStatusEnum.WAIT_RECEIVE.getInfo());
            orderAndItem.setOrderStatusList(orderStatusList);
        }
        //已完成的订单状态筛选条件
        if (StringUtils.isNotBlank(orderAndItem.getOrderStatus()) && StringUtils.equals(OrderStatusEnum.COMPLETE.getInfo(), orderAndItem.getOrderStatus())) {
            orderStatusList = Arrays.asList(OrderStatusEnum.COMPLETE.getInfo(), OrderStatusEnum.EVALUATED.getInfo());
            orderAndItem.setOrderStatusList(orderStatusList);
        }
        return nursePersonAppLoginMapper.selectOrderByNursePersonId(orderAndItem);
    }

    /**
     * 服务人员-服务订单详情
     *
     * @param orderNo 订单编号
     * @return 结果
     */
    @Override
    public AjaxResult selectOrderDetailsAndPatient(String orderNo) {
        OrderDetailsAndPatientVO patientByDetails = nursePersonAppLoginMapper.getOrderDetailsAndPatientByDetailsId(orderNo);
        if (Objects.nonNull(patientByDetails) && Objects.nonNull(patientByDetails.getBirthDate())) {
            patientByDetails.setAge(AgeUtil.getAgeMonth(String.valueOf(patientByDetails.getBirthDate())));
        }
        //健康状况
        List<PatientDiseaseInfo> patientDiseaseInfo = patientDiseaseInfoMapper.selectPatientDiseaseInfoByOrderNo(patientByDetails.getOrderNo());
        if (CollectionUtils.isNotEmpty(patientDiseaseInfo)) {
            List<String> diseaseNameList = patientDiseaseInfo.stream().filter(Objects::nonNull).map(PatientDiseaseInfo::getDiseaseName).filter(StringUtils::isNotBlank).collect(Collectors.toList());
            String diseaseName = String.join(",", diseaseNameList);
            patientByDetails.setDiseaseName(diseaseName);
        }
        return AjaxResult.success(patientByDetails);
    }

    /**
     * 服务人员 - 任务回退
     *
     * @param orderFallbackDTO 订单信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateAppointmentOrder(OrderFallbackDTO orderFallbackDTO) {
        AppointmentReceivingOrderVO appointmentReceivingOrder = appointmentOrderDetailsMapper.getAppointmentReceivingOrder(orderFallbackDTO.getAppointmentOrderNo());
        if (Objects.isNull(appointmentReceivingOrder)) {
            return AjaxResult.error("当前订单不存在，无法退回！");
        }
        appointmentReceivingOrder.setTaskReturnReason(orderFallbackDTO.getTaskReturnReason());
        int update = nursePersonAppLoginMapper.updateAppointmentOrderByOrderNo(orderFallbackDTO.getAppointmentOrderNo(), OrderStatusEnum.WAIT_DISPATCH.getInfo(), orderFallbackDTO.getTaskReturnReason());
        if (update <= 0) {
            throw new ServiceException("任务退回失败，请联系管理员！");
        }
        return AjaxResult.success();
    }

    /**
     * 任务确认完成
     *
     * @param appointmentOrderDetails 图片路径
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateOrderDetails(AppointmentOrderDetails appointmentOrderDetails) {
        AppointmentOrderRecordVO orderDetails = appointmentOrderDetailsMapper.selectAppointmentOrderById(appointmentOrderDetails.getOrderNo());
        if (Objects.isNull(orderDetails) || StringUtils.isBlank(orderDetails.getOrderStatus())) {
            return AjaxResult.error("当前订单状态不存在，请重新选择！");
        }
        if (!orderDetails.getOrderStatus().equals(OrderStatusEnum.NOT_FINISH.getInfo())) {
            return AjaxResult.error("订单状态异常，请选择未完成订单!");
        }
        if (StringUtils.isBlank(appointmentOrderDetails.getServeLocationLatitude()) || StringUtils.isBlank(appointmentOrderDetails.getServeLocationLatitude())) {
            log.info("当前用户不同意获取位置信息，无法保存当前位置经纬度信息！");
        }
        appointmentOrderDetails.setUpdateTime(LocalDateTime.now());
        appointmentOrderDetails.setOrderStatus(OrderStatusEnum.COMPLETE.getInfo());
        int update = appointmentOrderDetailsMapper.updateOrderDetailsById(appointmentOrderDetails);
        if (update <= 0) {
            throw new ServiceException("信息上传失败，请联系管理员！");
        }
        //新增护理员订单佣金收益信息表
        NurseStationPersonRevenue nurseStationPersonRevenue = new NurseStationPersonRevenue();
        nurseStationPersonRevenue.setNurseStationPersonId(Objects.isNull(orderDetails.getNurseStationPersonId()) ? null : orderDetails.getNurseStationPersonId());
        nurseStationPersonRevenue.setAppointmentOrderId(Objects.isNull(orderDetails.getId()) ? null : orderDetails.getId());
        nurseStationPersonRevenue.setRevenueAmount(Objects.isNull(orderDetails.getOrderCommissionAmount()) ? null : orderDetails.getOrderCommissionAmount());
        nurseStationPersonRevenue.setFinishOrderTime(LocalDateTime.now());
        nurseStationPersonRevenue.setCreateTime(LocalDateTime.now());
        int stationPersonRevenue = nurseStationPersonRevenueMapper.insertNurseStationPersonRevenue(nurseStationPersonRevenue);
        if (stationPersonRevenue <= 0) {
            throw new ServiceException("新增护理员订单佣金收益记录失败，请联系管理员！");
        }
        //更新护理员账户总金额
        Long nurseStationPersonId = Objects.isNull(orderDetails.getNurseStationPersonId()) ? 0 : orderDetails.getNurseStationPersonId();
        BigDecimal orderCommissionAmount = Objects.isNull(orderDetails.getOrderCommissionAmount()) ? BigDecimal.ZERO : orderDetails.getOrderCommissionAmount();
        nurseStationPersonMapper.updateTotalRevenueAmountById(nurseStationPersonId, orderCommissionAmount);
        return AjaxResult.success();
    }

    /**
     * 护理人员 注册用户信息
     *
     * @param nurseAppLogin 注册信息
     * @return com.xinyilu.common.core.domain.AjaxResult
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult nurseAppLoginSysUser(NurseAppLoginSysUserVO nurseAppLogin) {
        //校验手机号是否存在 sys_user 用户表与nurse_station_person 护理站人员信息表关联
        NurseStationPerson nurseStationPersonPhoneUser = nurseStationPersonMapper.getNurseStationPersonPhoneUser(nurseAppLogin.getPhonenumber());
        NurseAppLoginSysUserVO patient = new NurseAppLoginSysUserVO();
        if (Objects.nonNull(nurseStationPersonPhoneUser)) {
            patient.setNurseStationPersonId(Objects.isNull(nurseStationPersonPhoneUser.getId()) ? null : nurseStationPersonPhoneUser.getId());
        } else {
            log.warn("当前护理员信息在nurse_station_person表中不存在，请先前往Pc端护理站人员信息维护该护理人员信息！");
            return AjaxResult.error("当前护理员信息不存在，请前往护理站管理平台新增个人信息！");
        }
        //校验手机号是否存在 sys_user 用户表与nurse_station_person 护理站人员信息表关联
        int phoneCount = nursePersonAppLoginMapper.getSysUserPasswordByPhone(nurseAppLogin.getPhonenumber(), null);
        if (phoneCount > 0) {
            return AjaxResult.error("该手机号已注册，请重新输入！");
        }
        //调用md5加密方法
        String changePassword = md5(nurseAppLogin.getStationPersonPassword());
        patient.setPhonenumber(nurseAppLogin.getPhonenumber());
        patient.setUserName(nurseAppLogin.getPhonenumber());
        patient.setNickName(nurseAppLogin.getNickName());
        patient.setStationPersonPassword(changePassword);
        patient.setCreateTime(LocalDateTime.now());
        patient.setNurseStationIds(nurseAppLogin.getNurseStationIds());
        int row = nursePersonAppLoginMapper.insertNurseAppLoginSysUser(patient);
        if (row <= 0) {
            throw new ServiceException("注册失败，请联系管理员！");
        }
        return AjaxResult.success();
    }


    /**
     * app登录
     *
     * @param phonenumber           账号
     * @param stationPersonPassword 密码
     * @return AjaxResult
     */
    @Override
    public AjaxResult logins(String phonenumber, String stationPersonPassword) {
        if (BooleanUtils.isFalse(regexUtil.regexPhone(phonenumber))) {
            return AjaxResult.error("您输入的账号不正确，请重新输入！");
        }
        //校验手机号是否存在 sys_user 用户表与nurse_station_person 护理站人员信息表关联
        NurseStationPerson nurseStationPersonPhoneUser = nurseStationPersonMapper.getNurseStationPersonPhoneUser(phonenumber);
        if (Objects.isNull(nurseStationPersonPhoneUser)) {
            return AjaxResult.error("当前护理员信息不存在，请前往护理站管理平台新增个人信息！");
        }
        //判断账号是否存在，不存在进行注册
        int existsCount = nursePersonAppLoginMapper.getSysUserPasswordByPhone(phonenumber, null);
        if (existsCount <= 0) {
            return AjaxResult.error("当前账号不存在，请先注册！");
        }
        //账号存在，判断输入密码是否正确
        int count = nursePersonAppLoginMapper.getSysUserPasswordByPhone(phonenumber, md5(stationPersonPassword));
        if (count <= 0) {
            return AjaxResult.error("您输入的密码不正确，请重新输入！");
        }
        NursePersonAppLoginsUserVO patient = nursePersonAppLoginMapper.getUserAndPerson(phonenumber, md5(stationPersonPassword));
        return AjaxResult.success(patient);
    }

    /**
     * 忘记密码
     *
     * @param phonenumber           账号
     * @param stationPersonPassword 密码
     * @return 结果
     */
    @Override
    public AjaxResult updatePassword(String phonenumber, String stationPersonPassword, String verification) {
        //校验手机号是否存在 sys_user 用户表与nurse_station_person 护理站人员信息表关联
        NurseStationPerson nurseStationPersonPhoneUser = nurseStationPersonMapper.getNurseStationPersonPhoneUser(phonenumber);
        if (Objects.isNull(nurseStationPersonPhoneUser)) {
            return AjaxResult.error("当前护理员信息不存在，请前往护理站管理平台新增个人信息！");
        }
        Long patientId = nursePersonAppLoginMapper.getFromPhoneUserId(phonenumber);
        if (Objects.isNull(patientId) || patientId == 0L) {
            return AjaxResult.error("当前账号信息不存在，请重新输入！");
        }
        NurseAppLoginSysUserVO patientInfo = new NurseAppLoginSysUserVO();
        patientInfo.setPhone(phonenumber);
        patientInfo.setUserId(patientId);
        patientInfo.setStationPersonPassword(md5(stationPersonPassword));
        //判断是否修改成功`
        int updatePassword = nursePersonAppLoginMapper.updateUserPassWord(patientInfo);
        if (updatePassword <= 0) {
            throw new ServiceException("修改密码失败，请联系管理员！");
        }
        return AjaxResult.success();
    }

    /**
     * 查询护理站人员的个人信息
     *
     * @param nurseAppLoginSysUserVO 个人信息
     * @return com.xinyilu.nurseapplet.domain.vo.nursepersonapplogin.NursePersonAppLoginsUserVO
     **/
    @Override
    public NursePersonAppLoginsUserVO getNursePersonPersonalInformation(NurseAppLoginSysUserVO nurseAppLoginSysUserVO) {
        nurseAppLoginSysUserVO.setStationPersonPassword(md5(nurseAppLoginSysUserVO.getStationPersonPassword()));
        NursePersonAppLoginsUserVO personAppLoginsUserVO = nursePersonAppLoginMapper.getNursePersonPersonalInformation(nurseAppLoginSysUserVO);
        //查询所属的护理站信息
        if (StringUtils.isBlank(personAppLoginsUserVO.getNurseStationIds())) {
            return personAppLoginsUserVO;
        }
        List<String> nurseTypeCodeList = Arrays.asList(StringUtils.split(personAppLoginsUserVO.getNurseStationIds(), ","));
        List<Long> stationIdList = nurseTypeCodeList.stream().map(s -> Long.parseLong(s.trim())).distinct().collect(Collectors.toList());
        List<NurseStationSysUserVO> stationIds = nurseStationMapper.getNurseStationIds(stationIdList);
        personAppLoginsUserVO.setNurseStationSysUserVOList(stationIds);
        return personAppLoginsUserVO;
    }

    /**
     * 修改用户护理人员的账户密码
     *
     * @param nurseAppLoginSysUserVO 用户信息
     * @return int
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateUserPassWord(NurseAppLoginSysUserVO nurseAppLoginSysUserVO) {
        NurseStationPerson personInfo = nurseStationPersonMapper.getNurseStationPersonPhoneUser(nurseAppLoginSysUserVO.getPhonenumber());
        if (Objects.isNull(personInfo)) {
            return AjaxResult.error("当前护理人员信息不存在，无法修改个人信息！");
        }
        //有手机号才 进行校验
        if (StringUtils.isNotBlank(nurseAppLoginSysUserVO.getPhonenumber())) {
            if (BooleanUtils.isFalse(regexUtil.regexPhone(nurseAppLoginSysUserVO.getPhonenumber()))) {
                return AjaxResult.error("您输入的电话号码" + nurseAppLoginSysUserVO.getPhonenumber() + "不正确，请重新输入！");
            }
            if (StringUtils.isNotBlank(personInfo.getPhone()) && !StringUtils.equals(personInfo.getPhone(), nurseAppLoginSysUserVO.getPhonenumber())) {
                int nurseStationPersonPhone = nurseStationPersonMapper.getNurseStationPersonPhone(nurseAppLoginSysUserVO.getPhonenumber());
                if (nurseStationPersonPhone > 0) {
                    return AjaxResult.error("您输入的联系电话" + nurseAppLoginSysUserVO.getPhonenumber() + "重复！");
                }
            }
        }
        //更新sysUser表信息
        nursePersonAppLoginMapper.updateUserPassWord(nurseAppLoginSysUserVO);
        //更新NurseStationPerson表信息
        NurseStationPerson nurseStationPerson = new NurseStationPerson();
        nurseStationPerson.setNursePersonName(nurseAppLoginSysUserVO.getNickName());
        nurseStationPerson.setId(nurseAppLoginSysUserVO.getNurseStationPersonId());
        nurseStationPersonMapper.updateNurseStationPerson(nurseStationPerson);
        return AjaxResult.success();
    }

    /**
     * 修改被护理人人员上传文件头像
     *
     * @param avatar 头像地址
     * @param userId userId护理人人员id
     * @return com.xinyilu.common.core.domain.AjaxResult
     **/
    @Override
    public boolean updateHeadAvatarHeadUserId(Long userId, String avatar, String userIdAvatar) {
        //删除被护理人人员的头像
        if (StringUtils.isNotBlank(userIdAvatar)) {
            String picture = XinELuConfig.getProfile() + userIdAvatar.replaceAll("/profile", "");
            File checkReportNameFile = new File(picture);
            if (checkReportNameFile.exists()) {
                boolean delete = checkReportNameFile.delete();
                if (BooleanUtils.isFalse(delete)) {
                    throw new ServiceException("图片地址删除失败！");
                }
            }
        }
        return nursePersonAppLoginMapper.updateHeadAvatarHeadUserId(userId, avatar) > 0;
    }


    /**
     * 修改被护理人人员上传文件头像
     *
     * @param multipartFile 文件
     * @param userId        userId护理人人员id
     * @return com.xinyilu.common.core.domain.AjaxResult
     * @throws Exception 异常信息
     **/
    @Override
    public AjaxResult updateHeadAvatarHead(MultipartFile multipartFile, Long userId) throws Exception {
        //根据userId查询SysUser表的信息
        if (Objects.isNull(userId)) {
            return AjaxResult.error("当前用户信息不存在，无法上传！");
        }
        //根据被护理人的id查询基本信息
        NursePersonAppLoginsUserVO nursePersonUserId = nursePersonAppLoginMapper.getNursePersonUserId(userId);
        if (Objects.isNull(nursePersonUserId)) {
            return AjaxResult.error("当前用户信息不存在，无法上传！");
        }
        //原有用户头像地址
        String userIdAvatar = StringUtils.isBlank(nursePersonUserId.getAvatar()) ? "" : nursePersonUserId.getAvatar();
        //定义文件上传路径
        String fileName = FileUploadUtils.uploadPictureUrlPath(XinELuConfig.getProfile() + xinYiLuConfig.getNurseStationAppPersonUrl(), multipartFile, MimeTypeUtils.IMAGE_EXTENSION);
        if (StringUtils.isBlank(fileName)) {
            throw new Exception("头像上传失败，请联系管理员！");
        }
        if (nursePersonAppLoginService.updateHeadAvatarHeadUserId(userId, fileName, userIdAvatar)) {
            AjaxResult ajax = AjaxResult.success();
            ajax.put("imgUrl", fileName);
            return ajax;
        }
        return AjaxResult.success("上传成功！");
    }


    /**
     * 查询护理站列表
     *
     * @param nurseStation 护理站列表
     * @return com.xinyilu.base.domain.nursestation.NurseStation
     **/
    @Override
    public List<PersonNurseStationAppVO> getPersonNurseStationLists(PersonNurseStationAppVO nurseStation) {
        return nursePersonAppLoginMapper.getPersonNurseStationLists(nurseStation);
    }


    /**
     * 生成BCryptPasswordEncoder密码
     *
     * @param getStationPersonPassword 密码
     * @return 加密字符串
     */
    private String md5(String getStationPersonPassword) {
        getStationPersonPassword = Md5Utils.hash((getStationPersonPassword));
        return getStationPersonPassword;
    }
}
