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

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.xinelu.common.config.AppletChatConfig;
import com.xinelu.common.entity.AppletPhoneVO;
import com.xinelu.common.enums.CouponReceiveTypeEnum;
import com.xinelu.common.enums.CouponUseStatusEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.bean.BeanUtils;
import com.xinelu.common.utils.http.HttpService;
import com.xinelu.common.utils.http.HttpUtils;
import com.xinelu.common.utils.http.SslUtils;
import com.xinelu.common.utils.uuid.IdUtils;
import com.xinelu.familydoctor.applet.mapper.ResidentPatientInfoMapper;
import com.xinelu.familydoctor.applet.pojo.body.PatientInfoBody;
import com.xinelu.familydoctor.applet.pojo.entity.PatientInfo;
import com.xinelu.familydoctor.applet.service.IResidentPatientInfoService;
import com.xinelu.familydoctor.applet.utils.AppletAccessTokenUtils;
import com.xinelu.manage.domain.coupon.Coupon;
import com.xinelu.manage.domain.patientcouponreceive.PatientCouponReceive;
import com.xinelu.manage.domain.receiveAddressInfo.ReceiveAddressInfo;
import com.xinelu.manage.mapper.coupon.CouponMapper;
import com.xinelu.manage.mapper.patientcouponreceive.PatientCouponReceiveMapper;
import com.xinelu.manage.mapper.receiveAddressInfo.ReceiveAddressInfoMapper;
import com.xinelu.manage.vo.patientcouponreceive.PatientCouponReceiveInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 小程序注册Service业务层处理
 *
 * @author xinelu
 * @date 2023-09-25
 */
@Slf4j
@Service
public class ResidentPatientInfoServiceImpl implements IResidentPatientInfoService {

    @Resource
    private ResidentPatientInfoMapper residentPatientInfoMapper;
    @Resource
    private HttpService httpService;
    @Resource
    private AppletChatConfig appletChatConfig;
    @Resource
    private AppletAccessTokenUtils appletAccessTokenUtils;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private ReceiveAddressInfoMapper receiveAddressInfoMapper;
    @Resource
    private PatientCouponReceiveMapper patientCouponReceiveMapper;
    @Resource
    private CouponMapper couponMapper;

    /**
     * @return com.xinelu.familydoctor.applet.pojo.entity.PatientInfo
     * @Author mengkuiliang
     * @Description 获取注册详细信息
     * @Date 2023-09-21 021 9:44
     * @Param [registerCode]
     **/
    @Override
    public PatientInfo selectPatientInfoByCode(String patientCode) {
        return residentPatientInfoMapper.selectPatientInfoByCode(patientCode);
    }

    /**
     * @return int
     * @Author mengkuiliang
     * @Description 修改注册信息
     * @Date 2023-09-21 021 10:53
     * @Param [patientInfo]
     **/
    @Override
    public int updatePatientInfo(PatientInfo body) {
        return residentPatientInfoMapper.updatePatientInfo(body);
    }

    /**
     * @return java.lang.String
     * @Author mengkuiliang
     * @Description 获取OpenId
     * @Date 2023-09-21 021 9:19
     * @Param []
     **/
    @Override
    public String getOpenId(String code) {
        try {
            SslUtils.ignoreSsl();
            String params = "appid=" + appletChatConfig.getAppletId() + "&secret=" + appletChatConfig.getSecret() + "&js_code=" + code + "&grant_type=" + appletChatConfig.getGrantType();
//            log.info("获取openID请求参数{}", params);
            String result = HttpUtils.sendPost("https://api.weixin.qq.com/sns/jscode2session", params);
            JSONObject json = JSONObject.parseObject(result);
            // {"errcode":40029,"errmsg":"invalid code, rid: 650bf9c3-31a6c960-2b437029"}
//            log.info("获取openID响应结果{}", json.toJSONString());
            if (!json.containsKey("openid")) {
                throw new ServiceException(json.getString("errmsg"));
            }
            String openid = json.getString("openid");
            return openid;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @return java.lang.String
     * @Author mengkuiliang
     * @Description 获取微信手机号
     * @Date 2023-09-26 026 11:42
     * @Param [code]
     **/
    @Override
    public AppletPhoneVO getPhone(String code) throws Exception {
        JSONObject result;
        // 获取token
        String token_url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appletChatConfig.getAppletId(), appletChatConfig.getSecret());
        SslUtils.ignoreSsl();
        String tokenResult = HttpUtils.sendGet(token_url);
        if (tokenResult == null) {
            return null;
        }
        result = JSON.parseObject(tokenResult);
//        log.info("获取小程序token : {}", result.toJSONString());
        String accessToken = result.getString("access_token");
        if (StringUtils.isEmpty(accessToken)) {
            return null;
        }
        //获取手机号 https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber" + "?access_token=" + accessToken;
        JSONObject params = new JSONObject();
        params.put("code", code);
        SslUtils.ignoreSsl();
        result = httpService.post(url, null, params);
        return JSON.parseObject(result.toString(), AppletPhoneVO.class);
    }

    /**
     * @return java.lang.String
     * @Author mengkuiliang
     * @Description 身份证号是否已注册
     * @Date 2023-09-21 021 10:00
     * @Param [openId]
     **/
    public PatientInfo isRegisterByCardNo(String cardNo) {
        return residentPatientInfoMapper.isRegisterByCardNo(cardNo);
    }

    /**
     * @return void
     * @Author mengkuiliang
     * @Description 注册和完善信息
     * @Date 2023-09-21 021 10:14
     * @Param [body]
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(PatientInfoBody body) {
        if(StringUtils.isBlank(body.getCardNo())) {
            throw new ServiceException("请求参数有误");
        }
        // 查询已登录的居民信息
        PatientInfo loginPatientInfo = residentPatientInfoMapper.getLoginByOpenId(body.getOpenid());

        PatientInfo patientInfo;
        // 更新
        if (!StringUtils.isBlank(body.getPatientCode())) {
            patientInfo = residentPatientInfoMapper.getPatientInfoByPatientCode(body.getPatientCode());
            if(patientInfo == null) {
                throw new ServiceException("未查询到居民注册信息");
            }
            if(patientInfo.getDelFlag() != null && patientInfo.getDelFlag() == 1) {
                throw new ServiceException("居民已解绑，不能更新数据");
            }
            if(!body.getOpenid().equals(patientInfo.getBindOpenid())) {
                throw new ServiceException("该居民非当前账号绑定，不允许修改");
            }
            BeanUtils.copyBeanProp(patientInfo, body);
            // 已绑定openid，将该值置空
            if(loginPatientInfo != null) {
                patientInfo.setOpenid(null);
            }
            if (body.getDiseaseList() != null) {
                patientInfo.setDisease(body.getDiseaseList().stream().collect(Collectors.joining(",")));
            } else {
                patientInfo.setDisease("0");
            }
            patientInfo.setLoginFlag(1L);
            patientInfo.setBindOpenid(body.getOpenid());
            updatePatientInfo(patientInfo);
            // 新增
        } else {
            patientInfo = residentPatientInfoMapper.isRegisterByCardNo(body.getCardNo());
            if (patientInfo != null) {
                if(patientInfo.getDelFlag() == null || patientInfo.getDelFlag() == 0) {
                    throw new ServiceException("该身份证号已被注册");
                } else {
                    // 已解绑状态的更新
                    if(patientInfo.getDelFlag() == 1) {
                        patientInfo.setIsChecked("0");
                        // 已绑定openid，将该值置空
                        patientInfo.setOpenid(loginPatientInfo != null? null: body.getOpenid());
                        patientInfo.setUnionid(body.getUnionid());
                        patientInfo.setPatientName(body.getPatientName());
                        patientInfo.setPhone(body.getPhone());
                        patientInfo.setAddress(body.getAddress());
                        patientInfo.setUpdateTime(new Date());
                        patientInfo.setUpdateBy(body.getCardNo());
                        patientInfo.setHeadPictureUrl(body.getHeadPictureUrl());
                        patientInfo.setDelFlag(0);
                        patientInfo.setLoginFlag(1L);
                        if (body.getDiseaseList() != null) {
                            patientInfo.setDisease(body.getDiseaseList().stream().collect(Collectors.joining(",")));
                        } else {
                            patientInfo.setDisease("0");
                        }
                        patientInfo.setBindOpenid(body.getOpenid());
                        patientInfo.setBindingTime(new Date());
                        residentPatientInfoMapper.updatePatientInfo(patientInfo);
                    }
                }
                // 注册
            } else {
                List<PatientInfo> list = residentPatientInfoMapper.getList(body.getOpenid(), null);
                if(list != null && list.size() >= 8) {
                    throw new ServiceException("同一个微信最多绑定8个居民");
                }
                PatientInfo entity = new PatientInfo();
                BeanUtils.copyBeanProp(entity, body);
                // 已绑定openid，将该值置空
                if(loginPatientInfo != null) {
                    entity.setOpenid(null);
                }
                if (body.getDiseaseList() != null) {
                    entity.setDisease(body.getDiseaseList().stream().collect(Collectors.joining(",")));
                } else {
                    entity.setDisease("0");
                }
                entity.setPatientCode(IdUtils.fastSimpleUUID());
                entity.setBindingTime(new Date());
                entity.setIsChecked("0");
                entity.setCreateTime(new Date());
                entity.setCreateBy(body.getCardNo());
                entity.setLoginFlag(1L);
                entity.setDelFlag(0);
                entity.setBindOpenid(body.getOpenid());
                residentPatientInfoMapper.insertPatientInfo(entity);

                // 新增的话重新查询居民信息获取patientId
                patientInfo = residentPatientInfoMapper.getPatientInfoByPatientCode(entity.getPatientCode());

            }
        }

        // 记录收货地址信息
        if(patientInfo != null) {
            // 如果置空了，重新赋值
            if(StringUtils.isBlank(patientInfo.getOpenid())) {
               patientInfo.setOpenid(body.getOpenid());
            }
            this.insertReceiveAddress(patientInfo);
        }
        PatientInfo patient = residentPatientInfoMapper.getLoginByOpenId(body.getOpenid());
        //判断是否是第一次完善，如果是则发放新人优惠券信息
        PatientCouponReceive patientCouponReceive = new PatientCouponReceive();
        patientCouponReceive.setReceiveSource(CouponReceiveTypeEnum.NEW_PEOPLE_WELFARE.getInfo());
        patientCouponReceive.setPatientId(patient.getId());
        int couponReceiveCount = patientCouponReceiveMapper.getCouponReceiveByReceiveSource(patient.getId(), CouponReceiveTypeEnum.NEW_PEOPLE_WELFARE.getInfo());
        if (Objects.nonNull(patient.getLoginFlag()) && patient.getLoginFlag() ==1 && couponReceiveCount <= 0) {
           issueCoupons(patient);
        }
    }

    /** 新增收货人地址信息 */
    private void insertReceiveAddress(PatientInfo patientInfo) {
        //判断当前收货地址信息是否存在
        int receiveCount = receiveAddressInfoMapper.getReceiveAddressInfo(patientInfo.getId(), patientInfo.getPatientName(), patientInfo.getPhone(), patientInfo.getAddress());
        if (receiveCount > 0) {
            return;
        }
        //添加收货人地址信息
        ReceiveAddressInfo receiveAddressInfo = new ReceiveAddressInfo();
        receiveAddressInfo.setReceiveAddress(patientInfo.getAddress());
        receiveAddressInfo.setReceivePhone(patientInfo.getPhone());
        receiveAddressInfo.setAreaCode(patientInfo.getAreaCode());
        receiveAddressInfo.setPatientId(patientInfo.getId());
        receiveAddressInfo.setReceiveName(patientInfo.getPatientName());
        receiveAddressInfo.setOpenid(patientInfo.getOpenid());
        receiveAddressInfo.setUnionid(patientInfo.getUnionid());
        receiveAddressInfo.setCreateTime(LocalDateTime.now());
        receiveAddressInfo.setCreateBy(patientInfo.getCardNo());
        int insertReceiveAddressInfo = receiveAddressInfoMapper.insertReceiveAddressInfo(receiveAddressInfo);
        if (insertReceiveAddressInfo <= 0) {
            throw new ServiceException("修改收货人地址信息失败,请联系管理员！");
        }
    }

    /**
     * @return void
     * @Author mengkuiliang
     * @Description 解绑
     * @Date 2023-09-21 021 10:50
     * @Param [cardNo]
     **/
    @Override
    public void unbinding(String patientCode) {
        PatientInfo register = residentPatientInfoMapper.selectPatientInfoByCode(patientCode);
        if (register == null || String.valueOf(register.getDelFlag()).equals("1")) {
            return;
        }
        register.setIsChecked("0");
        register.setOpenid(null);
        register.setDelFlag(1);
        register.setBindOpenid("");
        residentPatientInfoMapper.updatePatientInfo(register);
    }

    /**
     * @return java.lang.String
     * @Author mengkuiliang
     * @Description 获取已注册列表
     * @Date 2023-09-21 021 14:52
     * @Param [openid]
     **/
    @Override
    public List<PatientInfo> getList(String openid, String cityCode) {
        return residentPatientInfoMapper.getList(openid, cityCode);
    }

    /**
     * @return void
     * @Author mengkuiliang
     * @Description 切换账号
     * @Date 2023-09-21 021 15:18
     * @Param [registerCode]
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PatientInfo switchResident(String openid, String patientCode) {
        PatientInfo register = residentPatientInfoMapper.selectPatientInfoByCode(patientCode);
        if (register == null) {
            throw new ServiceException("该账号未注册不能切换");
        } else {
            if (StringUtils.isBlank(register.getBindOpenid())) {
                throw new ServiceException("该账号未注册不能切换");
            }
            if (!openid.equals(register.getBindOpenid())) {
                throw new ServiceException("该账号已被其他人绑定不能切换");
            }
            residentPatientInfoMapper.switchResident(openid, patientCode);
        }
        PatientInfo patientInfo = residentPatientInfoMapper.selectPatientInfoByCode(patientCode);
        if(patientInfo != null && StringUtils.isBlank(patientInfo.getOpenid())) {
            patientInfo.setOpenid(openid);
        }
        return patientInfo;
    }

    /** 判断2个参数是否一样 */

    /**
     * @return java.lang.String
     * @Author mengkuiliang
     * @Description 获取当前注册居民
     * @Date 2023-09-25 025 15:29
     * @Param [openid]
     **/
    @Override
    public PatientInfo getCurrentResident(String openid, String cityCode) {
        List<PatientInfo> list = residentPatientInfoMapper.getList(openid, null);
        if (list == null || list.size() == 0) {
            return null;
        }
        PatientInfo patientInfo = null;
        // 获取当前登录的居民
        List<PatientInfo> currentList = list.stream().filter(p -> p.getIsChecked().equals("1")).collect(Collectors.toList());
        if (currentList.size() > 0) {
            if (!StringUtils.isBlank(currentList.get(0).getDisease())) {
                currentList.get(0).setDiseaseList(Arrays.asList(currentList.get(0).getDisease().split(",")));
            }
            patientInfo = currentList.get(0);
            // 没有已选择的，则取最新注册的一条数据
        } else {

            // 更新选择标识
            residentPatientInfoMapper.updateChecked(list.get(0).getPatientCode(), "1");

            if (!StringUtils.isBlank(list.get(0).getDisease())) {
                list.get(0).setDiseaseList(Arrays.asList(list.get(0).getDisease().split(",")));
            }
            list.get(0).setIsChecked("1");
            list.get(0).setOpenid(openid);
            patientInfo = list.get(0);
        }
        return patientInfo;
    }

    /**
     * @return com.xinelu.familydoctor.applet.pojo.entity.PatientInfo
     * @Author mengkuiliang
     * @Description 获取注册信息-根据身份证号
     * @Date 2023-09-27 027 15:13
     * @Param [cardNo]
     **/
    @Override
    public PatientInfo getByCardNo(String cardNo) {
        return residentPatientInfoMapper.getByCardNo(cardNo);
    }

    /**
     * @return com.xinelu.familydoctor.applet.pojo.entity.PatientInfo
     * @Author mengkuiliang
     * @Description 是否已注册
     * @Date 2023-10-11 011 10:46
     * @Param [code]
     **/
    /*@Override
    public PatientInfo isRegistered(String code) {
        return getCurrentResident(getOpenId(code), null);
    }*/
    @Override
    public HashMap<String, String> login(String loginCode, String phoneCode) throws Exception {
        HashMap<String, String> resultMap = new HashMap<>();
        try {
            SslUtils.ignoreSsl();
            String params = "appid=" + appletChatConfig.getAppletId() + "&secret=" + appletChatConfig.getSecret() + "&js_code=" + loginCode + "&grant_type=" + appletChatConfig.getGrantType();
//            log.info("获取openID请求参数{}", params);
            String result = HttpUtils.sendPost("https://api.weixin.qq.com/sns/jscode2session", params);
            JSONObject json = JSONObject.parseObject(result);
            // {"errcode":40029,"errmsg":"invalid code, rid: 650bf9c3-31a6c960-2b437029"}
//            log.info("获取openID响应结果{}", json.toJSONString());
            if (!json.containsKey("openid")) {
                throw new ServiceException(json.getString("errmsg"));
            }
            String openid = json.getString("openid");
            resultMap.put("openid", openid);

            //获取手机号
            AppletPhoneVO phone = getPhone(phoneCode);
            String phoneNumber = phone.getPhoneInfo().getPhoneNumber();
            resultMap.put("phone", phoneNumber);
            List<PatientInfo> infoList = residentPatientInfoMapper.selectPatientInfoByPhone(phoneNumber);
            if(infoList != null && infoList.size() > 0) {
                if(!infoList.get(0).getBindOpenid().equals(openid)) {
                    resultMap.put("code", "2");
                    resultMap.put("info", "已被其他人注册");
                    return resultMap;
                } else {
                    resultMap.put("code", "1");
                    resultMap.put("info", "已注册");
                    return resultMap;
                }
            }
            resultMap.put("code", "0");
            resultMap.put("info", "未注册");
            return resultMap;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 发放优惠券方法胡
     *
     * @param patient 会员信息
     */
    public void issueCoupons(PatientInfo patient ) {
        PatientCouponReceiveInfoVO receiveInfoVO = new PatientCouponReceiveInfoVO();
        //查询新人福利的优惠券列表信息
        Coupon coupon = new Coupon();
        Long patientId = patient.getId();
        coupon.setReceiveType(CouponReceiveTypeEnum.NEW_PEOPLE_WELFARE.getInfo());
        List<Coupon> couponList = couponMapper.selectCouponList(coupon);
        if (CollectionUtils.isEmpty(couponList)) {
            return ;
        }
        //组装优惠券信息
        List<PatientCouponReceive> couponReceiveList = Lists.newArrayList();
        for (Coupon couponInfo : couponList) {
            if (Objects.isNull(couponInfo.getId())) {
                continue;
            }
            PatientCouponReceive couponReceive = new PatientCouponReceive();
            couponReceive.setPatientId(patientId);
            couponReceive.setCouponId(couponInfo.getId());
            couponReceive.setReceiveSource(CouponReceiveTypeEnum.NEW_PEOPLE_WELFARE.getInfo());
            couponReceive.setUseStatus(CouponUseStatusEnum.WAIT_RECEIVE.getInfo());
            couponReceive.setExpirationStartTime(LocalDateTime.now());
            couponReceive.setExpirationEndTime(LocalDate.now().plusDays(Objects.isNull(couponInfo.getCouponReductionDays()) ? 0 : couponInfo.getCouponReductionDays()).atTime(23, 59, 59));
            couponReceive.setReceiveTime(LocalDateTime.now());
            couponReceive.setCouponReductionDays(Objects.isNull(couponInfo.getCouponReductionDays()) ? 0 : couponInfo.getCouponReductionDays());
            couponReceive.setCreateTime(LocalDateTime.now());
            couponReceive.setCouponTitle(StringUtils.isBlank(couponInfo.getCouponTitle()) ? "" : couponInfo.getCouponTitle());
            couponReceive.setCouponPrice(Objects.isNull(couponInfo.getCouponPrice()) ? BigDecimal.ZERO : couponInfo.getCouponPrice());
            couponReceive.setCouponConsumePrice(Objects.isNull(couponInfo.getCouponConsumePrice()) ? BigDecimal.ZERO : couponInfo.getCouponConsumePrice());
            couponReceive.setCouponDescription(StringUtils.isBlank(couponInfo.getCouponDescription()) ? "" : couponInfo.getCouponDescription());
            couponReceiveList.add(couponReceive);
        }
        if (CollectionUtils.isNotEmpty(couponReceiveList)) {
            int insertCount = patientCouponReceiveMapper.insertBatchPatientReceive(couponReceiveList);
            if (insertCount <= 0) {
                log.error("完善用户信息接口-新人送券执行失败，输入参数[{}]", couponReceiveList);
                throw new ServiceException("完善用户信息失败，请联系管理员！");
            }
        }
    }
}
