package com.yihu.wlyy.web.common.account;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.yihu.wlyy.entity.login.LoginLog;
import com.yihu.wlyy.entity.patient.SocialSecurityInfo;
import com.yihu.wlyy.repository.patient.PatientDao;
import com.yihu.wlyy.repository.patient.SocialSecurityInfoDao;
import com.yihu.wlyy.service.app.family.FamilyService;
import com.yihu.wlyy.service.common.login.LoginLogService;
import com.yihu.wlyy.util.HttpUtil;
import com.yihu.wlyy.util.MD5;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.entity.security.Token;
import com.yihu.wlyy.service.common.SMSService;
import com.yihu.wlyy.service.common.account.PatientService;
import com.yihu.wlyy.service.common.account.TokenService;
import com.yihu.wlyy.task.PushMsgTask;
import com.yihu.wlyy.util.IdcardValidator;
import com.yihu.wlyy.util.RSAUtils;
import com.yihu.wlyy.web.WeixinBaseController;

/**
 * @author calvin
 */
@Controller
@RequestMapping(value = "/weixin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Api(description = "微信端用户注册")
public class WechatController extends WeixinBaseController {

    @Autowired
    private PatientService patientService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SMSService smsService;
    @Autowired
    private SocialSecurityInfoDao socialSecurityInfoDao;
    @Autowired
    private PatientDao patientDao;
    @Autowired
    private FamilyService familyService;
    @Autowired
    private LoginLogService loginLogService;

    /**
     * 患者注册-验证手机号
     *
     * @param phone 登录手机号
     * @return
     */
    @RequestMapping(value = "checkmobile")
    @ResponseBody
    public String checkmobile(String phone) {
        try {
            Patient temp = patientService.findByMobile(phone);
            if (temp != null) {
                JSONObject json = new JSONObject();
                // 设置患者标识
                json.put("code", temp.getCode());
                // 设置身份证号
                json.put("idcard", temp.getIdcard());
                return write(200, "患者信息查询成功！", "data", json);
            }
            return error(1, "该手机号未被注册");
        } catch (Exception e) {
            error(e);
            return error(-1, "手机号验证失败");
        }
    }

    /**
     * 患者注册-验证身份证
     *
     * @param idcard 身份證號
     * @param mobile 登录手机号
     * @return
     */
    @RequestMapping(value = "checkidcard")
    @ResponseBody
    public String checkidcard(String idcard, String mobile) {
        try {
            // 解密身份证号
            idcard = RSAUtils.getInstance(patientService).decryptString(idcard);
            idcard = URLDecoder.decode(idcard, "UTF-8");
            idcard = StringUtils.reverse(idcard);
            Patient temp = patientService.findByIdcard(idcard);
            if (temp != null) {
                JSONObject json = new JSONObject();
                // 设置患者标识
                json.put("code", temp.getCode());
                // 设置手机号码
                json.put("mobile", temp.getMobile());
                // 设置身份证号
                json.put("idcard", temp.getIdcard());
                return write(1, "患者信息查询成功！", "data", json);
            } else {
                Patient temp1 = patientService.findByMobile(mobile);
                if (temp1 != null) {
                    JSONObject json = new JSONObject();
                    // 设置患者标识
                    json.put("code", temp1.getCode());
                    // 设置手机号码
                    json.put("mobile", temp1.getMobile());
                    // 设置身份证号
                    json.put("idcard", temp1.getIdcard());
                    return write(2, "患者信息查询成功！", "data", json);
                }
            }
            return success("该身份证和手机号未被注册");
        } catch (Exception e) {
            error(e);
            return error(-1, "身份证验证失败");
        }
    }

    /**
     * 注册信息验证
     *
     * @param name   姓名
     * @param idcard 身份证号
     * @param ssc    社保卡号
     * @param mobile 手机号
     * @return
     */
    @RequestMapping(value = "/check_regist_info")
    @ResponseBody
    public String checkRegistInfo(String name, String idcard, String ssc, String mobile) {
        try {
            if (StringUtils.isEmpty(name)) {
                return error(-1, "姓名不允许为空");
            }
            if (StringUtils.isEmpty(idcard)) {
                return error(-1, "身份证号不允许为空");
            }
            if (StringUtils.isEmpty(ssc)) {
                return error(-1, "社保卡号不允许为空");
            }
            if (StringUtils.isEmpty(mobile)) {
                return error(-1, "手机号不允许为空");
            }
            if (patientService.findByMobile(mobile) != null) {
                return error(-1, "该手机号已被注册");
            }
            // 解密身份证号
            idcard = RSAUtils.getInstance(patientService).decryptString(idcard);
            idcard = URLDecoder.decode(idcard, "UTF-8");
            idcard = StringUtils.reverse(idcard);
            // 校验身份证号
            IdcardValidator validator = new IdcardValidator();
            if (validator.isValidatedAllIdcard(idcard)) {
                if (idcard.length() == 15) {
                    idcard = validator.convertIdcarBy15bit(idcard);
                    if (StringUtils.isEmpty(idcard)) {
                        return error(-1, "请输入正确的身份证号");
                    }
                }
            } else {
                return error(-1, "请输入正确的身份证号");
            }

            SocialSecurityInfo socialSecurityInfo = socialSecurityInfoDao.findBySfzh18Max(idcard);

            if (socialSecurityInfo != null) {
                if (name.compareTo(socialSecurityInfo.getXming0() == null ? "" : socialSecurityInfo.getXming0()) != 0) {
                    return error(-1, "身份证号与姓名不一致，请检查后重新输入");
                }
                if (ssc.compareTo(socialSecurityInfo.getCardno() == null ? "" : socialSecurityInfo.getCardno()) != 0 && ssc.compareTo(socialSecurityInfo.getCard16() == null ? "" : socialSecurityInfo.getCard16()) != 0) {
                    return error(-1, "身份证号与医保卡号不一致，请检查后重新输入");
                }
            } else {
                return error(-1, "对不起，暂不支持16年6月份之后办理的医保卡注册");
            }

            Patient patient = patientDao.findByIdcard(idcard);

            if (patient != null) {
                if (!StringUtils.isEmpty(patient.getMobile())) {
                    return error(-1, "该身份证已被注册");
                }
            }

            return write(200, "验证成功");
        } catch (Exception e) {
            return error(-1, "验证失败");
        }
    }

    /**
     * 患者注册
     *
     * @param idcard  身份證號
     * @param mobile  登录手机号
     * @param captcha 手机验证码
     * @return
     */
    @RequestMapping(value = "regist")
    @ResponseBody
    public String regist(String name,
                         String idcard,
                         String ssc,
                         String mobile,
                         String captcha,
                         String openid,
                         String password) {
        try {
            if (StringUtils.isEmpty(name)) {
                return error(-1, "姓名不允许为空！");
            }
            if (StringUtils.isEmpty(idcard)) {
                return error(-1, "身份证号不允许为空！");
            }
            if (StringUtils.isEmpty(ssc)) {
                return error(-1, "社保卡号不允许为空！");
            }
            if (StringUtils.isEmpty(mobile)) {
                return error(-1, "手机号不允许为空！");
            }
            if (patientService.findByMobile(mobile) != null) {
                return error(-1, "该手机号已被注册！");
            }
            // 对验证码进行校验
            int res = smsService.check(mobile, 1, captcha);
            switch (res) {
                case -2:
                    return error(-1, "验证码已过期！");
                case -1:
                    return error(-1, "请输入正确的验证码！");
                case 0:
                    return error(-1, "验证码无效！");
            }
            // 未绑定openid，查询是否绑定其他账号
//			if (patientService.countByOpenid(openid) > 0) {
//				return error(-1, "该微信号已绑定其他手机号！");
//			}
            // 解密身份证号
            idcard = RSAUtils.getInstance(patientService).decryptString(idcard);
            idcard = URLDecoder.decode(idcard, "UTF-8");
            idcard = StringUtils.reverse(idcard);
            // 校验身份证号
            IdcardValidator validator = new IdcardValidator();
            if (validator.isValidatedAllIdcard(idcard)) {
                if (idcard.length() == 15) {
                    idcard = validator.convertIdcarBy15bit(idcard);
                    if (StringUtils.isEmpty(idcard)) {
                        return error(-1, "请输入正确的身份证号！");
                    }
                }
            } else {
                return error(-1, "请输入正确的身份证号！");
            }

            SocialSecurityInfo socialSecurityInfo = socialSecurityInfoDao.findBySfzh18Max(idcard);

            if (socialSecurityInfo != null) {
                if (name.compareTo(socialSecurityInfo.getXming0() == null ? "" : socialSecurityInfo.getXming0()) != 0) {
                    return error(-1, "身份证号与姓名不一致<br/>请检查后重新输入");
                }
                if (ssc.compareTo(socialSecurityInfo.getCardno() == null ? "" : socialSecurityInfo.getCardno()) != 0) {
                    if (ssc.compareTo(socialSecurityInfo.getCard16() == null ? "" : socialSecurityInfo.getCard16()) != 0) {
                        return error(-1, "身份证号与医保卡号不一致，请检查后重新输入");
                    } else {
                        ssc = socialSecurityInfo.getCardno();//统一只存英文字母开头的医保卡
                    }
                }
            } else {
                return error(-1, "对不起，暂不支持16年6月份之后办理的医保卡注册");
            }

            Patient patient = patientDao.findByIdcard(idcard);

            if (patient == null) {
                patient = new Patient();
            } else {
                if (!StringUtils.isEmpty(patient.getMobile())) {
                    return error(-1, "该身份证已被注册！");
                }
            }
            patient.setName(name);
            patient.setIdcard(idcard);
            patient.setMobile(mobile);
            //增加密码
            String salt = UUID.randomUUID().toString().replace("-", "");
            patient.setSalt(salt);
            password = RSAUtils.getInstance(patientService).decryptString(password);
            password = StringUtils.reverse(password);
            patient.setPassword(MD5.GetMD5Code(password + salt));
            patient.setSsc(ssc);
            if(!org.springframework.util.StringUtils.isEmpty(openid)){
                patient.setOpenid(openid);
                patient.setOpenidTime(new Date());
            }
            JSONObject json = patientService.register(idcard, ssc, name, mobile, MD5.GetMD5Code(password + salt)
                    , salt, openid, 3);
            if (json != null) {
                // 注册成功
                return write(200, "注册成功！", "data", json);
            } else {
                // 注册失败
                return error(-1, "注册失败！");
            }
        } catch (Exception e) {
            error(e);
            return error(-1, "注册失败！");
        }
    }

    /**
     * 患者微信登录接口
     *
     * @param captcha  短信号
     * @param mobile   电话号码
     * @param password 登录密码
     * @return
     */
    @RequestMapping(value = "login")
    @ResponseBody
    public String login(
            @RequestParam(required = false) String mobile,
            @RequestParam(required = false) String captcha,
            @RequestParam(required = false) String password,
            String openid) {
        System.out.println("login openid : " + openid );
        String errorMessage;
        LoginLog loginLog = new LoginLog();
        loginLog.setCreateTime(new Date());
        loginLog.setPhone(mobile);
        loginLog.setType("2");
        loginLog.setUserType("1");
        try {
            //账号登录 mobile可能是电话号也可能是身份证
            if (StringUtils.isNoneEmpty(mobile) && StringUtils.isNoneEmpty(password) && !org.springframework.util.StringUtils.isEmpty(mobile)) {
                Patient patient = patientService.findByMobile(mobile);
                if (patient == null) {
                    patient = patientService.findByIdcard(mobile);
                }
                loginLog.setLoginType("2");
                if (patient == null) {
                    if (mobile.length() == 11) {
                        errorMessage = "该手机号暂未注册账号，请确认后重新输入！";
                    } else {
                        errorMessage = "该身份证号暂未注册账号，请确认后重新输入！";
                    }
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else if (patient.getStatus() == 0) {
                    if (mobile.length() == 11) {
                        errorMessage = "该手机号已被禁止使用！";
                    } else {
                        errorMessage = "该身份证号已被禁止使用！";
                    }
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else if (patient.getStatus() == 2) {
                    errorMessage = "该账号正在审核中，请确认审核通过后再登录，“如有疑问，拨打400-6677-400转2人工客服”";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else if (StringUtils.isEmpty(openid)) {
                    errorMessage = "无效的OpenID！";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                }
                loginLog.setUserCode(patient.getCode());
                //解密
                password = RSAUtils.getInstance(patientService).decryptString(password);
                password = StringUtils.reverse(password);
                //生成MD5
                String loginPassword = MD5.GetMD5Code(password + patient.getSalt());
                //判断d登录密码是否正确
                if (loginPassword.equals(patient.getPassword())) {
                    // 绑定用户手机号和openid
                    if (!StringUtils.equals(patient.getOpenid(), openid)) {
                        //patient.setOpenid(openid);
                        patientService.updatePatient(patient, openid);
                    }

                    // 用户校验通过，生成token
                    Token token = tokenService.newTxToken(patient.getCode(), openid);
                    Map<Object, Object> map = new HashMap<Object, Object>();
                    map.put("id", patient.getId());
                    map.put("uid", patient.getCode());
                    map.put("name", patient.getName());
                    map.put("token", token.getToken());
                    map.put("photo", patient.getPhoto());
                    if (StringUtils.isNoneEmpty(openid)) {
                        //发送微信模板
                        familyService.sendWXMessage(patient);
                    }

                    loginLog.setLoginType("1");
                    loginLogService.saveLog(loginLog);
                    return write(200, "登录成功", "data", map);
                } else {
                    errorMessage = "密码错误,登录失败";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                }
            }
            //短信登录
            if (StringUtils.isNoneEmpty(mobile) && StringUtils.isNoneEmpty(captcha)) {
                // 对验证码进行校验
                int res = smsService.check(mobile, 4, captcha);
                switch (res) {
                    case -2: {
                        errorMessage = "验证码已过期！";
                        loginLog.setErrorMessage(errorMessage);
                        loginLogService.saveLog(loginLog);
                        return error(-1, errorMessage);
                    }
                    case -1: {
                        errorMessage = "请输入正确的验证码！";
                        loginLog.setErrorMessage(errorMessage);
                        loginLogService.saveLog(loginLog);
                        return error(-1, errorMessage);
                    }
                    case 0: {
                        errorMessage = "验证码无效！";
                        loginLog.setErrorMessage(errorMessage);
                        loginLogService.saveLog(loginLog);
                        return error(-1, errorMessage);
                    }
                }
                Patient patient = patientService.findByMobile(mobile);
                loginLog.setLoginType("1");
                if (patient == null) {
                    if (mobile.length() == 11) {
                        errorMessage = "该手机号暂未注册账号，请确认后重新输入！";
                    } else {
                        errorMessage = "该身份证号暂未注册账号，请确认后重新输入！";
                    }
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else if (patient.getStatus() == 0) {
                    if (mobile.length() == 11) {
                        errorMessage = "该手机号已被禁止使用！";
                    } else {
                        errorMessage = "该身份证号已被禁止使用！";
                    }
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else if (patient.getStatus() == 2) {
                    errorMessage = "该账号正在审核中，请确认审核通过后再登录，“如有疑问，拨打400-6677-400转2人工客服”";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else if (StringUtils.isEmpty(openid)) {
                    errorMessage = "无效的OpenID！";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                }
                loginLog.setUserCode(patient.getCode());
                // 绑定用户手机号和openid
                if (!StringUtils.equals(patient.getOpenid(), openid)) {
                    //patient.setOpenid(openid);
                    patientService.updatePatient(patient, openid);
                }

                // 用户校验通过，生成token
                Token token = tokenService.newTxToken(patient.getCode(), openid);
                Map<Object, Object> map = new HashMap<Object, Object>();
                map.put("id", patient.getId());
                map.put("uid", patient.getCode());
                map.put("name", patient.getName());
                map.put("token", token.getToken());
                map.put("photo", patient.getPhoto());
                if (StringUtils.isNoneEmpty(openid)) {
                    //发送微信模板
                    familyService.sendWXMessage(patient);
                }
                loginLog.setType("1");
                loginLogService.saveLog(loginLog);
                return write(200, "登录成功", "data", map);
            }
            return error(-1, "登录失败");
        } catch (Exception e) {

            errorMessage = "系统异常，登录失败";
            loginLog.setErrorMessage(errorMessage);
            loginLogService.saveLog(loginLog);
            error(e);
            return error(-1, "系统异常，登录失败");
        }
    }

    /**
     * 获取签名signature
     *
     * @param pageUrl 需要签名的页面全地址（？后的也需要除了#后的不需要）
     * @return
     */
    @RequestMapping(value = "getSign")
    @ResponseBody
    public String getSign(String pageUrl) {
        try {
            String ticket = getJsapi_ticketByToken();
            if (ticket != null) {
                String noncestr = UUID.randomUUID().toString();
                long timestamp = System.currentTimeMillis() / 1000;
                String url = pageUrl;
                String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
                // sha1加密
                String signature = SHA1(str);

                Map<Object, Object> map = new HashMap<Object, Object>();
                map.put("noncestr", noncestr);
                map.put("timestamp", timestamp);
                map.put("signature", signature);
                return write(200, "获取签名成功", "data", map);
            } else
                return error(-1, "获取签名失败");

        } catch (Exception e) {
            error(e);
        }
        return error(-1, "获取签名失败");
    }

    /**
     * 发送微信签约成功的消息
     *
     * @param code 患者编号
     * @return
     */
    @RequestMapping(value = "sendSign")
    @ResponseBody
    public String sendSignSucess(String code) {
        try {
            Patient patient = patientService.findByCode(code);
            JSONObject json = new JSONObject();
            json.put("first", "开始");
            json.put("remark", "指导备注");
            json.put("date", "2016-06-08");
            json.put("doctorName", "徐小鹏");
            json.put("orgName", "厦门第一医院");
            PushMsgTask.getInstance().putWxMsg(getAccessToken(), 5, patient.getOpenid(), patient.getName(), json);
            return write(200, "发送成功");
        } catch (Exception e) {
            error(e);
            return error(-1, "发送失败");
        }
    }

    /**
     * 获取微信用户身份
     * @param code
     * @return
     */
    // @RequestMapping(value = "identity")
    // @ResponseBody
    // public String identity(String code) {
    // try {
    // String openid = getOpenid();
    // if(StringUtils.isEmpty(openid)){
    // openid = getOpenidByCode(code);
    // }
    // if (StringUtils.isEmpty(openid)) {
    // return error(-1, "获取openid异常！");
    // }
    // JSONObject userAgent = new JSONObject();
    // Patient patient = patientService.findByOpenid(openid);
    // long id = 0;
    // String uid = "";
    // String name = "";
    // String photo = "";
    // String tokenStr = "";
    // if (patient != null) {
    // id = patient.getId();
    // uid = patient.getCode();
    // name = patient.getName();
    // photo = patient.getPhoto();
    // // 查询token
    // Token token = SystemData.wxPatientTokens.get(patient.getCode());
    // if (token == null) {
    // // 从数据库加载
    // token = tokenService.findWxToken(patient.getCode());
    // }
    // if (token == null) {
    // // 生成新的token
    // token = tokenService.newTxToken(patient.getCode(), openid);
    // }
    // tokenStr = token.getToken();
    // }
    // userAgent.put("id", id);
    // userAgent.put("uid", uid);
    // userAgent.put("openid", openid);
    // userAgent.put("name", name);
    // userAgent.put("photo", photo);
    // userAgent.put("token", tokenStr);
    // return write(200, "获取身份信息成功！", "data", userAgent);
    // } catch (Exception e) {
    // error(e);
    // return error(-1, "获取身份信息失败！");
    // }
    // }

    /**
     * 获取微信openid
     *
     * @param code
     * @return
     */
    @RequestMapping(value = "getOpenidByCode")
    @ResponseBody
    public String getOpenidByCode(String code) {
        try {
            String openid = super.getOpenidByCode(code);
            if (!StringUtils.isEmpty(openid)) {
                return write(200, "获取openid成功！", "openid", openid);
            } else {
                return error(-1, "获取openid失败！");
            }
        } catch (Exception e) {
            error(e);
            return error(-1, "获取openid失败！");
        }
    }

    /**
     * 判断是否关注
     *
     * @param openid
     * @return
     */
    @RequestMapping(value = "/is_subscribe")
    @ResponseBody
    public String getIsSubscribe(String openid) {
        try {
            String userInfo_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + getAccessToken() + "&openid=" + openid + "&lang=zh_CN";
            String params = "";
            String result = HttpUtil.sendGet(userInfo_url, params);
            JSONObject json = new JSONObject(result);
            if (json.has("subscribe")) {
                return write(200, "查询成功", "subsribe", json.get("subscribe").toString());
            } else {
                return error(-1, json.getString("errmsg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return error(-1, "查询失败");
        }
    }
}
