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

import com.alibaba.fastjson2.JSONObject;
import com.xinelu.applet.dto.appletlogin.StationItemInfoDTO;
import com.xinelu.applet.mapper.appletlogin.AppletLoginMapper;
import com.xinelu.applet.mapper.nurseapplogin.NurseAppLoginMapper;
import com.xinelu.applet.service.nurseapplogin.NurseAppLoginService;
import com.xinelu.applet.utils.AppointmentTimeUtil;
import com.xinelu.applet.vo.appletlogin.NurserStationItemConsumableVO;
import com.xinelu.applet.vo.appletlogin.NurserStationItemInfoVO;
import com.xinelu.applet.vo.nurseapplogin.AppLoginVO;
import com.xinelu.applet.vo.nurseapplogin.PatientAndDiseaseVO;
import com.xinelu.applet.vo.nursepersonapplogin.OrderAndItemVO;
import com.xinelu.applet.vo.specialdisease.WeekDaysVO;
import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.enums.*;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.AgeUtil;
import com.xinelu.common.utils.http.HttpService;
import com.xinelu.common.utils.http.HttpUtils;
import com.xinelu.common.utils.spring.SpringUtils;
import com.xinelu.manage.domain.appointmentorder.AppointmentOrder;
import com.xinelu.manage.domain.goodsOrder.GoodsOrder;
import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper;
import com.xinelu.manage.mapper.sysarea.SysAreaMapper;
import com.xinelu.manage.vo.patientinfo.PatientInfoVO;
import com.xinelu.manage.vo.sysarea.SysAreaVO;
import com.xinelu.system.domain.SysConfig;
import com.xinelu.system.mapper.SysConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description APP登录注册业务层实现类
 * @Author ZH
 * @Date 2022-10-12
 */
@Service
@Slf4j
public class NurseAppLoginServiceImpl implements NurseAppLoginService {

    @Resource
    private NurseAppLoginMapper nurseAppLoginMapper;
    @Resource
    private AppletLoginMapper appletLoginMapper;
    @Resource
    private SysAreaMapper sysAreaMapper;
    @Resource
    private AppointmentTimeUtil appointmentTimeUtil;
    @Resource
    private SysConfigMapper sysConfigMapper;
    @Resource
    private PatientInfoMapper patientInfoMapper;
    @Resource
    private HttpService httpService;

    /**
     * 判断用户是否完善信息-微信小程序和APP共用
     *
     * @param patientId 用户id
     * @return 结果
     */
    @Override
    public AjaxResult getIdentification(Long patientId) {
        //判断当前用户信息是否存在
        PatientInfoVO patientInfo = patientInfoMapper.getPatientInfoById(patientId);
        if (Objects.isNull(patientInfo)) {
            return AjaxResult.error("当前用户信息不存在，无法完善个人信息！");
        }
        AppLoginVO appLoginVO = new AppLoginVO();
        appLoginVO.setLoginFlag(Objects.nonNull(patientInfo.getLoginFlag()) && patientInfo.getLoginFlag() == 1);
        return AjaxResult.success(appLoginVO);
    }

    /**
     * 查询护理人列表信息
     *
     * @param patientId 用户id
     * @return 护理人列表信息集合
     */
    @Override
    public AjaxResult getPatientVOList(Long patientId) {
        PatientAndDiseaseVO patientVOList = nurseAppLoginMapper.getPatientDiseaseByPatientId(patientId);
        if (StringUtils.isBlank(patientVOList.getAreaCode())) {
            return AjaxResult.success(patientVOList);
        }
        // 获取本护理站的区域信息
        if (StringUtils.isNotBlank(patientVOList.getAreaCode())) {
            SysAreaVO nurseStationAreaByList = sysAreaMapper.getNurseStationAreaByCode(patientVOList.getAreaCode());
            if (Objects.isNull(nurseStationAreaByList)) {
                return AjaxResult.success(patientVOList);
            }
            String provinceName = StringUtils.isBlank(nurseStationAreaByList.getProvinceName()) ? "" : nurseStationAreaByList.getProvinceName();
            String cityName = StringUtils.isBlank(nurseStationAreaByList.getCityName()) ? "" : nurseStationAreaByList.getCityName();
            String regionName = StringUtils.isBlank(nurseStationAreaByList.getRegionName()) ? "" : nurseStationAreaByList.getRegionName();
            String streetName = StringUtils.isBlank(nurseStationAreaByList.getStreetName()) ? "" : nurseStationAreaByList.getStreetName();
            patientVOList.setAreaName(provinceName + cityName + regionName + streetName);
        } else {
            patientVOList.setAreaName("");
        }
        return AjaxResult.success(patientVOList);
    }

    /**
     * app根据护理站id和护理站项目id查询对应的护理项目信息
     *
     * @param itemInfoDTO 输入参数
     * @return 护理站项目集合
     */
    @Override
    public AjaxResult getAppStationItemAndConsumableInfo(StationItemInfoDTO itemInfoDTO) {
        //查询护理站项目信息
        NurserStationItemInfoVO itemInfo = appletLoginMapper.getNurserStationItemInfo(itemInfoDTO.getStationId(), itemInfoDTO.getStationItemId(), itemInfoDTO.getStationItemPriceId());
        if (Objects.isNull(itemInfo)) {
            return AjaxResult.error("当前护理项目信息不存在！");
        }
        itemInfo.setAdvanceAppointDuration(StringUtils.isBlank(itemInfo.getAdvanceAppointDuration()) ? "" : itemInfo.getAdvanceAppointDuration());
        //护理耗材总价格
        BigDecimal consumableTotalPrice = BigDecimal.ZERO;
        //查询护理站项目耗材信息
        List<NurserStationItemConsumableVO> itemConsumableList = appletLoginMapper.getItemConsumableList(itemInfoDTO.getStationId(), itemInfoDTO.getStationItemId());
        if (CollectionUtils.isNotEmpty(itemConsumableList)) {
            //计算护理项目价格 = 数量 * 单价
            itemConsumableList.forEach(item -> {
                if (Objects.nonNull(item.getConsumablePrice()) && Objects.nonNull(item.getConsumableCount())) {
                    item.setConsumablePrice(item.getConsumablePrice().multiply(BigDecimal.valueOf(item.getConsumableCount())).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
            });
            consumableTotalPrice = itemConsumableList.stream().map(NurserStationItemConsumableVO::getConsumablePrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            itemInfo.setItemConsumableList(itemConsumableList);
        }
        //耗材总价格
        itemInfo.setConsumableTotalPrice(consumableTotalPrice);
        //应付总金额 = 护理项目价格 + 耗材总价格
        BigDecimal nurseItemPrice = Objects.isNull(itemInfo.getNurseItemPrice()) ? BigDecimal.ZERO : itemInfo.getNurseItemPrice();
        itemInfo.setTotalPrice(nurseItemPrice.add(consumableTotalPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
        //获取近七天的预约时间点
        List<String> keyList = Arrays.asList("MORNING_START_TIME", "MORNING_END_TIME",
                "AFTERNOON_START_TIME", "AFTERNOON_END_TIME", AppointmentTimeIntervalEnum.HALF_HOUR.getValue());
        Map<String, String> keysMap = sysConfigMapper.getSystemConfigByKeys(keyList).stream()
                .filter(item -> StringUtils.isNotBlank(item.getConfigKey()) && StringUtils.isNotBlank(item.getConfigValue()))
                .collect(Collectors.toMap(SysConfig::getConfigKey, SysConfig::getConfigValue));
        if (keysMap.isEmpty()) {
            keysMap.put("HALF_HOUR", "HALF_HOUR");
            keysMap.put("MORNING_START_TIME", "08:00:00");
            keysMap.put("MORNING_END_TIME", "12:00:00");
            keysMap.put("AFTERNOON_START_TIME", "13:30:00");
            keysMap.put("AFTERNOON_END_TIME", "18:00:00");
        }
        String timeInterval = StringUtils.isBlank(itemInfo.getAppointmentTimeInterval()) ? keysMap.getOrDefault("HALF_HOUR", AppointmentTimeIntervalEnum.HALF_HOUR.getValue()) : itemInfo.getAppointmentTimeInterval();
        itemInfo.setAppointmentTimeInterval(timeInterval);
        LocalTime morningOpenStartTime = Objects.isNull(itemInfo.getMorningOpenStartTime()) ? LocalTime.parse(keysMap.getOrDefault("MORNING_START_TIME", "08:00:00")) : itemInfo.getMorningOpenStartTime();
        itemInfo.setMorningOpenStartTime(morningOpenStartTime);
        LocalTime morningOpenEndTime = Objects.isNull(itemInfo.getMorningOpenEndTime()) ? LocalTime.parse(keysMap.getOrDefault("MORNING_END_TIME", "12:00:00")) : itemInfo.getMorningOpenEndTime();
        itemInfo.setMorningOpenEndTime(morningOpenEndTime);
        LocalTime afternoonOpenStartTime = Objects.isNull(itemInfo.getAfternoonOpenStartTime()) ? LocalTime.parse(keysMap.getOrDefault("AFTERNOON_START_TIME", "13:30:00")) : itemInfo.getAfternoonOpenStartTime();
        itemInfo.setAfternoonOpenStartTime(afternoonOpenStartTime);
        LocalTime afternoonOpenEndTime = Objects.isNull(itemInfo.getAfternoonOpenEndTime()) ? LocalTime.parse(keysMap.getOrDefault("AFTERNOON_END_TIME", "18:00:00")) : itemInfo.getAfternoonOpenEndTime();
        itemInfo.setAfternoonOpenEndTime(afternoonOpenEndTime);
        List<WeekDaysVO> appointmentTimeList = appointmentTimeUtil.getAppointmentTimeList(timeInterval, morningOpenStartTime, morningOpenEndTime, afternoonOpenStartTime, afternoonOpenEndTime);
        itemInfo.setAppointmentTimeList(appointmentTimeList);
        return AjaxResult.success(itemInfo);
    }

    /**
     * 个人中心查询
     *
     * @param patientId 会员id
     * @return 结果
     */
    @Override
    public AjaxResult nurseAppPersonal(Long patientId, String region) {
        PatientAndDiseaseVO patientDisease = nurseAppLoginMapper.getPatientDiseaseByPatientId(patientId);
        if (Objects.nonNull(patientDisease) && Objects.nonNull(patientDisease.getBirthDate())) {
            patientDisease.setAge(AgeUtil.getAgeMonth(String.valueOf(patientDisease.getBirthDate())));
            patientDisease.setId(patientId);
        }
        if (Objects.nonNull(patientDisease) && StringUtils.isNotBlank(patientDisease.getDisease())) {
            patientDisease.setDiseaseList(Arrays.stream(patientDisease.getDisease().split(","))
                    .map(Integer::valueOf)
                    .toArray(Integer[]::new));
        }
        if (Objects.nonNull(patientDisease) && StringUtils.isNotBlank(patientDisease.getAreaCode())) {
            SysAreaVO codeName = sysAreaMapper.getSubordinateRegionsFindSuperiorRegions(patientDisease.getAreaCode());
            if (Objects.nonNull(codeName)) {
                String provinceName = StringUtils.isBlank(codeName.getProvinceName()) ? "" : codeName.getProvinceName();
                String cityName = StringUtils.isBlank(codeName.getCityName()) ? "" : codeName.getCityName();
                String regionName = StringUtils.isBlank(codeName.getRegionName()) ? "" : codeName.getRegionName();
                String streetName = StringUtils.isBlank(codeName.getStreetName()) ? "" : codeName.getStreetName();
                patientDisease.setAreaName(provinceName + cityName + regionName + streetName);
            } else {
                patientDisease.setAreaName("");
            }
        } else {
            patientDisease.setAreaName("");
        }
        patientDisease.setCityCode(region);
        // 更新签约编号
        setSignInfo(patientDisease);
        //查询所有商品订单
        List<GoodsOrder> goodsOrders = nurseAppLoginMapper.selectGoodsOrderListByPatient(patientId, OrderTypeEnum.HEALTH_CONSULTATION.getInfo());
        if (CollectionUtils.isEmpty(goodsOrders)) {
            return AjaxResult.success(patientDisease);
        }
        //计算待付款订单、待收货订单、待评价订单、已完成订单数量
        long waitPayCount = goodsOrders.stream().filter(Objects::nonNull).filter(item -> StringUtils.isNotBlank(item.getOrderStatus())).filter(item -> GooodsOrderStatusEnum.WAIT_PAY.getInfo().equals(item.getOrderStatus())).count();
        long waitReceivedGoodsCount = goodsOrders.stream().filter(Objects::nonNull).filter(item -> StringUtils.isNotBlank(item.getOrderStatus())).filter(item -> GooodsOrderStatusEnum.WAIT_RECEIVED_GOODS.getInfo().equals(item.getOrderStatus())).count();
        long receivedGoodsCount = goodsOrders.stream().filter(Objects::nonNull).filter(item -> StringUtils.isNotBlank(item.getOrderStatus())).filter(item -> GooodsOrderStatusEnum.RECEIVED_GOODS.getInfo().equals(item.getOrderStatus())).count();
        patientDisease.setWaitPayCount(waitPayCount);
        patientDisease.setWaitReceivedGoodsCount(waitReceivedGoodsCount);
        patientDisease.setReceivedGoodsCount(receivedGoodsCount);

        return AjaxResult.success(patientDisease);
    }

    // 更新签约编号
    private void setSignInfo(PatientAndDiseaseVO patientDisease) {
        if (!StringUtils.isBlank(patientDisease.getCityCode())) {
            try {
                String result = (String) httpService.get(SpringUtils.getFdUrl(patientDisease.getCityCode()) + "/resident/signinfo/detail/" + patientDisease.getCardNo(), null, String.class);
                JSONObject jsonObject = JSONObject.parseObject(result);
                if (jsonObject.getInteger("code") == 1) {
                    String signNo = "";
                    if (jsonObject.getJSONObject("data") != null) {
                        JSONObject signInfo = jsonObject.getJSONObject("data");
                        if (signInfo.containsKey("signNo")) {
                            signNo = signInfo.getString("signNo");

                            // 查询居民健康积分
                            getResidentScore(patientDisease);

                        }
                    } else {
                        signNo = null;
                    }
                    // 不一致才更新签约编号
                    if (!String.valueOf(signNo).equals(String.valueOf(patientDisease.getSignNo()))) {
                        patientInfoMapper.updateSignNo(patientDisease.getPatientId(), signNo);
                        patientDisease.setSignNo(signNo);
                    }
                }
            } catch (Exception e) {
                log.error("更新签约编号出错：{}", e.getMessage());
            }
        }
    }

    // 查询居民健康积分
    private void getResidentScore(PatientAndDiseaseVO patientDisease) {
        String result = HttpUtils.sendGet(SpringUtils.getFdUrl(patientDisease.getCityCode()) + "/patient/score/record/total/" + patientDisease.getCardNo());
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!jsonObject.get("code").toString().equals("1")) {
            log.error("查询居民健康积分出错：{}", jsonObject.get("msg").toString());
        } else {
            patientDisease.setScore(jsonObject.getString("data"));
        }
    }

    /**
     * App查询预约服务订单
     *
     * @param patientId   用户id
     * @param orderStatus 预约订单状态
     * @return 结果
     */
    @Override
    public List<OrderAndItemVO> selectAppServiceOrderItem(Long patientId, String orderStatus) {
        List<OrderAndItemVO> appointmentOrderDetails = new ArrayList<>();
        if (Objects.isNull(patientId) && StringUtils.isBlank(orderStatus)) {
            return appointmentOrderDetails;
        }
        return nurseAppLoginMapper.selectAppointmentOrderDetailsByPatientId(patientId, orderStatus);
    }

    /**
     * 小程序取消订单
     *
     * @param appointmentOrderId      预约订单编号
     * @param cancelAppointmentReason 取消预约原因
     * @return 结果
     */
    @Override
    public AjaxResult updateAppointmentOrder(Long appointmentOrderId, String cancelAppointmentReason) {
        AppointmentOrder appointmentOrder = new AppointmentOrder();
        appointmentOrder.setUpdateTime(LocalDateTime.now());
        appointmentOrder.setId(appointmentOrderId);
        appointmentOrder.setCancelAppointmentReason(cancelAppointmentReason);
        appointmentOrder.setConfirmRefundStatus(ConfirmRefundStatusEnum.NOT_CONFIRM.getInfo());
        appointmentOrder.setOrderStatus(OrderStatusEnum.WAIT_REFUND.getInfo());
        int update = nurseAppLoginMapper.updateAppointmentByOrderId(appointmentOrder);
        if (update <= 0) {
            throw new ServiceException("取消订单失败，请联系管理员！");
        }
        return AjaxResult.success();
    }
}
