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

import com.yihu.wlyy.entity.doctor.profile.Doctor;
import com.yihu.wlyy.entity.login.LoginLog;
import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.entity.security.Token;
import com.yihu.wlyy.repository.security.TokenDao;
import com.yihu.wlyy.service.common.SMSService;
import com.yihu.wlyy.service.common.account.DoctorService;
import com.yihu.wlyy.service.common.account.PatientService;
import com.yihu.wlyy.service.common.account.RoleService;
import com.yihu.wlyy.service.common.account.TokenService;
import com.yihu.wlyy.service.common.login.LoginLogService;
import com.yihu.wlyy.util.DateUtil;
import com.yihu.wlyy.util.MD5;
import com.yihu.wlyy.util.RSAUtils;
import com.yihu.wlyy.util.SystemData;
import com.yihu.wlyy.web.BaseController;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.patchca.color.SingleColorFactory;
import org.patchca.filter.predefined.*;
import org.patchca.service.ConfigurableCaptchaService;
import org.patchca.utils.encoder.EncoderHelper;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.List;

//import io.swagger.annotations.Api;

/**
 * @author calvin
 */
@Controller
@RequestMapping(value = "/login", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Api(description = "患者、医生及管理员登录")
public class LoginController extends BaseController {

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private PatientService patientService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SMSService smsService;

    @Autowired
    public TokenDao tokenDao;

    @Autowired
    private RoleService roleService;
    @Autowired
    private LoginLogService loginLogService;

    /**
     * 公钥生成并返回接口
     *
     * @return
     */
    @RequestMapping(value = "public_key")
    @ResponseBody
    public String publicKey() {
        try {
            String modulus = RSAUtils.getInstance(smsService).getModulus();
            String exponent = RSAUtils.getInstance(smsService).getExponent();
            if (StringUtils.isEmpty(modulus) || StringUtils.isEmpty(exponent)) {
                return error(-1, "公钥获取失败！");
            } else {
                JSONObject json = new JSONObject();
                json.put("modulus", modulus);
                json.put("exponent", exponent);
                return write(200, "公钥获取成功！", "data", json);
            }
        } catch (Exception e) {
            return error(-1, "公钥获取失败！");
        }
    }

    // @RequestMapping(value = "testPush")
    // @ResponseBody
    // public String testPush(String receiver, String type, String title, String msg, String data) throws JSONException, InterruptedException {
    // PushMsgTask.getInstance().put(receiver, type, title, msg, data);
    // return "OK";
    // }
    //
    // @RequestMapping(value = "test_public_key")
    // @ResponseBody
    // public String testPublicKey(String str) {
    // try {
    // String modulus = RSAUtils.getInstance(smsService).getModulus();
    // String exponent = RSAUtils.getInstance(smsService).getExponent();
    //
    // String temp = RSAUtils.getInstance(smsService).decryptStringByJs(str);
    // System.out.println(temp);
    // temp = URLDecoder.decode(temp, "UTF-8");
    // System.out.println(temp);
    //
    // if (StringUtils.isEmpty(modulus) || StringUtils.isEmpty(exponent)) {
    // return error(-1, "公钥获取失败！");
    // } else {
    // JSONObject json = new JSONObject();
    // json.put("modulus", modulus);
    // json.put("exponent", exponent);
    // return write(200, "公钥获取成功！", "data", json);
    // }
    // } catch (Exception e) {
    // return error(-1, "公钥获取失败！");
    // }
    // }

    /**
     * 医生登录接口
     *
     *  @param mobile  手机号
     * @param captcha 短信验证码
     * @param idcard  身份证号
     * @param password 密码
     * @return
     */
    @RequestMapping(value = "doctor")
    @ResponseBody
    public String doctor(@RequestParam(required = false) String mobile,
                         @RequestParam(required = false) String captcha,
                         @RequestParam(required = false) String idcard,
                         @RequestParam(required = false) String password) {
        String errorMessage;
        LoginLog loginLog=new LoginLog();
        loginLog.setCreateTime(new Date());
        loginLog.setPhone(mobile);
        loginLog.setType("2");
        loginLog.setUserType("2");
        loginLog.setAppVersion(super.getAppVersion());
        try {
            if (StringUtils.isEmpty(getIMEI())) {
                errorMessage="获取手机IMEI码失败！";
                loginLog.setErrorMessage(errorMessage);
                loginLogService.saveLog(loginLog);
                return error(-1, errorMessage);
            }
            //身份证登录
            if(StringUtils.isNoneEmpty(mobile)&&StringUtils.isNoneEmpty(password)){
                password = RSAUtils.getInstance(doctorService).decryptString(password);
                password=StringUtils.reverse(password);
                Doctor doctor=doctorService.findDoctorByMobile(mobile);
                loginLog.setLoginType("2");
                if(doctor==null){
                    errorMessage="该号码未注册！";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1,errorMessage);
                }
                loginLog.setUserCode(doctor.getCode());
                String loginPassword= MD5.GetMD5Code(password+doctor.getSalt());
                if(loginPassword.equals(doctor.getPassword())){
                    // 用户校验通过，生成token
                    Token token = tokenService.newToken(doctor.getCode(), getIMEI(), 2);
                    loginLog.setTokenId(token.getId());
                    loginLog.setType("1");
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", doctor.getId());
                    map.put("uid", doctor.getCode());
                    map.put("token", token.getToken());
                    map.put("name", doctor.getName());
                    map.put("hospital", doctor.getHospital());
                    map.put("photo", doctor.getPhoto());
                    // 设置医生类型：1专科医生，2全科医生，3健康管理师
                    map.put("doctorType", doctor.getLevel());
                    //获取医生角色和区域权限
                    List<Map<String, String>> roleMap = roleService.getUserRoleAndArea(doctor.getCode());
                    map.put("userRole", roleMap);
                    if("10".equals(doctor.getLevel())&&roleMap.size()==0){
                        errorMessage="改用户没有管理员权限";
                        loginLog.setErrorMessage(errorMessage);
                        loginLogService.saveLog(loginLog);
                        return error(-1, errorMessage);
                    }
                    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, 5, 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);}
                }
                Doctor doctor = doctorService.findDoctorByMobile(mobile);
                loginLog.setLoginType("1");
                if (doctor == null) {
                     errorMessage="该手机号未注册，请确认！";
                    loginLog.setErrorMessage(errorMessage);
                    loginLogService.saveLog(loginLog);
                    return error(-1, errorMessage);
                } else {
                    loginLog.setUserCode(doctor.getCode());
                    // 用户校验通过，生成token
                    Token token = tokenService.newToken(doctor.getCode(), getIMEI(), 2);
                    loginLog.setTokenId(token.getId());
                    loginLog.setType("1");
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", doctor.getId());
                    map.put("uid", doctor.getCode());
                    map.put("token", token.getToken());
                    map.put("name", doctor.getName());
                    map.put("hospital", doctor.getHospital());
                    map.put("photo", doctor.getPhoto());
                    // 设置医生类型：1专科医生，2全科医生，3健康管理师
                    map.put("doctorType", doctor.getLevel());
                    //获取医生角色和区域权限
                    List<Map<String, String>> roleMap = roleService.getUserRoleAndArea(doctor.getCode());
                    map.put("userRole", roleMap);
                    if("10".equals(doctor.getLevel())&&roleMap.size()==0){
                        errorMessage="改用户没有管理员权限";
                        loginLog.setErrorMessage(errorMessage);
                        loginLogService.saveLog(loginLog);
                        return error(-1, errorMessage);
                    }
                    loginLogService.saveLog(loginLog);
                    return write(200, "登录成功", "data", map);
                }
            }
            errorMessage="登录信息不完整，请重新输入！";
            loginLog.setErrorMessage(errorMessage);
            loginLogService.saveLog(loginLog);
            return error(-1,errorMessage);
        } catch (Exception e) {
            loginLog.setErrorMessage(e.getMessage());
            loginLogService.saveLog(loginLog);
            error(e);
            return error(-1, "系统异常，登录失败");
        }
    }

    /**
     * 忘记密码
     *
     * @param type    1患者端，2医生端
     * @param idcard  患者身份证号
     * @param mobile  手机号
     * @param captcha 手机验证码
     * @param newpwd  新密码
     * @return
     */
    @RequestMapping(value = "forgetpwd")
    @ResponseBody
    public String forgetpwd(int type,
                            @RequestParam(required = false) String idcard,
                            @RequestParam(required = false) String mobile,
                            @RequestParam(required = false) String captchaToken,
                            @RequestParam(required = false)String captcha,
                            @RequestParam(required = false)String patient,
                            String newpwd) {
        try {
            //String ct = request.getSession().getAttribute("captchaToken").toString();
//            if (StringUtils.isEmpty(captchaToken)) {
//                return error(-1, "图形验证码不允许为空！");
//            }
//            if (!StringUtils.equalsIgnoreCase(captchaToken, ct)) {
//                return error(-1, "图形验证码错误！");
//            }
//            idcard = RSAUtils.getInstance(doctorService).decryptString(idcard);
//            idcard = URLDecoder.decode(idcard, "UTF-8");
//            idcard = StringUtils.reverse(idcard);
//            newpwd = RSAUtils.getInstance(doctorService).decryptString(newpwd);
//            newpwd = URLDecoder.decode(newpwd, "UTF-8");
//            newpwd = StringUtils.reverse(newpwd);
            // 对验证码进行校验


            if (type == 2) {
                // 医生端
                    Doctor doctor = doctorService.findDoctorByMobile(mobile);
                    String password = RSAUtils.getInstance(doctorService).decryptString(newpwd);
                    password=StringUtils.reverse(password);
                    password=MD5.GetMD5Code(password+doctor.getSalt());
                    doctor.setPassword(password);
                    doctorService.updateDoctorPwd(doctor);
                    return success("操作成功！");
            } else {
                // 患者端
                Patient patientTemp = patientService.findByIdcard(idcard);
                if (patientTemp == null) {
                    return error(-1, "操作失败：此用户未注册");
                } else {
                    String password = RSAUtils.getInstance(doctorService).decryptString(newpwd);
                    password=StringUtils.reverse(password);
                    password=MD5.GetMD5Code(password+patientTemp.getSalt());
                    patientTemp.setPassword(password);
                    patientService.updatePatientPwd(patientTemp);
                    return success("操作成功！");
                }
            }
        } catch (Exception e) {
            error(e);
            return error(-1, "系统异常，操作失败");
        }
    }

    /**
     * 退出登录
     *
     * @param type 1患者，2医生，3微信公众号
     * @return
     */
    @RequestMapping(value = "exit")
    @ResponseBody
    public String logout(int type) {
        try {
            tokenService.delToken(type, getUID());
            return success("已成功退出！");
        } catch (Exception e) {
            error(e);
            return invalidUserException(e, -1, "操作失败！");
        }
    }

    @RequestMapping(value = "/third/login")
    @ResponseBody
    public String thirdLogin(
            @RequestParam(value = "id") int id,
            @RequestParam(value = "uid") String uid,
            @RequestParam(value = "imei") String imei,
            @RequestParam(value = "token") String tokenStr,
            @RequestParam(value = "platform") int platform) {

        try {
            if (StringUtils.isEmpty(tokenStr) || StringUtils.isEmpty(imei) || StringUtils.isEmpty(uid)) {
                // response.getWriter().write(error(SystemConf.NOT_LOGIN, "请登录后再操作！"));
                return error(-1, "系统异常，操作失败");
            }

            Token token = SystemData.doctorTokens.get(uid);
            if (token == null) {
                token = tokenDao.findByToken(tokenStr);
                if (token != null) {
                    // 加入缓存
                    SystemData.doctorTokens.put(uid, token);
                }
            }
            if (token == null || token.getPlatform() != 2) {
                // 未登录

                return error(-1, "系统异常，操作失败");
            } else {
                if (token.getTimeout().getTime() < new Date().getTime()) {
                    // 登录超时

                    return error(-1, "系统异常，操作失败");
                } else if (!StringUtils.equals(uid, token.getUser()) || !StringUtils.equals(imei, token.getImei())) {
                    // 别处登录

                    return error(-1, "系统异常，操作失败");
                } else {
                    // 一天只更新一次
                    if (DateUtil.getDays(token.getCzrq(), DateUtil.getNowDateShort()) != 0) {
                        // 今天未更新，则更新缓存
                        token.setCzrq(new Date());
                        // 更新内存
                        SystemData.doctorTokens.put(uid, token);
                        // 更新数据库
                        tokenDao.save(token);
                    }
                }
            }
            return success("登陆成功");
        } catch (Exception ex) {
            error(ex);
            return error(-1, "系统异常，操作失败");
        }
    }

    // public String getLoginInfo()
    // {
    // try{
    // Token token = SystemData.doctorTokens.get(tokenStr);
    // return "";
    // }
    // catch(Exception ex)
    // {
    // error(ex);
    // return error(-1, "系统异常，操作失败");
    // }
    // }

    /**
     * 验证码地址
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("pcrimg")
    public void crimg(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ConfigurableCaptchaService cs = new ConfigurableCaptchaService();
        cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170)));
        Random random = new Random();
        switch (random.nextInt(5)) {
            case 0:
                cs.setFilterFactory(new CurvesRippleFilterFactory(cs.getColorFactory()));
                break;
            case 1:
                cs.setFilterFactory(new MarbleRippleFilterFactory());
                break;
            case 2:
                cs.setFilterFactory(new DoubleRippleFilterFactory());
                break;
            case 3:
                cs.setFilterFactory(new WobbleRippleFilterFactory());
                break;
            case 4:
                cs.setFilterFactory(new DiffuseRippleFilterFactory());
                break;
        }
        HttpSession session = request.getSession(false);
        if (session == null) {
            session = request.getSession();
        }
        setResponseHeaders(response);
        String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.getOutputStream());
        session.setAttribute("captchaToken", token);
    }

    protected void setResponseHeaders(HttpServletResponse response) {
        response.setContentType("image/png");
        response.setHeader("Cache-Control", "no-cache, no-store");
        response.setHeader("Pragma", "no-cache");
        long time = System.currentTimeMillis();
        response.setDateHeader("Last-Modified", time);
        response.setDateHeader("Date", time);
        response.setDateHeader("Expires", time);
    }

    // @RequestMapping(value = "test_sms")
    // @ResponseBody
    // public String testSms() {
    // try {
    // JSONObject params = new JSONObject();
    // params.put("SpCode", SystemConf.SMS_SP_CODE);
    // params.put("LoginName", SystemConf.SMS_LOGIN_NAME);
    // params.put("Password", SystemConf.SMS_PASSWORD);
    // params.put("MessageContent", "您的找回密码验证码为：123456");
    // params.put("UserNumber", "18559687019");
    // params.put("SerialNumber", "");
    // params.put("ScheduleTime", "");
    // params.put("f", 1);
    // String result = HttpClientUtil.post(SystemConf.SMS_URL, SMSService.buildSmsParams("您的找回密码验证码为：123456", "18559687019"), "GBK");
    // JSONObject json = SMSService.toJson(result);
    // System.out.println(json.toString());
    // System.out.println(json.getInt("result"));
    // if (json.getInt("result") != 0) {
    // return error(-1, "短信发送失败！");
    // }
    // return success("短信发送成功！");
    // } catch (Exception e) {
    // error(e);
    // return error(-1, "短信发送失败！");
    // }
    // }
    /**
     * 患者，医生注册-验证手机号
     *
     * @param mobile 登录手机号
     * @return
     */
    @RequestMapping(value = "checkmobile")
    @ResponseBody
    public String checkmobile(@RequestParam(required = true,value = "mobile",defaultValue = "0")String mobile,
                              @RequestParam(required = true,value = "type",defaultValue = "0") int type) {
        try {
            if(type==0){//患者端
                List<Patient> temp = patientService.findByMobile(mobile);
                if (temp != null&&temp.size()>0) {
                    // 设置身份证号
                    return write(200, "手机号码已经被注册！");
                }
                return error(-1, "该手机号未被注册！");
            }else if(type==1){
                Doctor doctor = doctorService.findDoctorByMobile(mobile);
                if(doctor!=null){
                    return write(200, "手机号码已经被注册！");
                }
                return error(-1, "该手机号未被注册！");
            }else{
                return error(1, "错误的请求类型！");
            }
        } catch (Exception e) {
            error(e);
            return error(-1, "手机号验证失败");
        }
    }
}
