package com.iamberry.wechat.service.phone;

import com.iamberry.app.config.ImberryConfig;
import com.iamberry.app.tool.log.RatFWLogger;
import com.iamberry.wechat.core.entity.phone.PhoneCode;
import com.iamberry.wechat.face.phone.PhoneCodeService;
import com.iamberry.wechat.service.mapper.PhoneCodeMapper;
import com.iamberry.wechat.tools.ResponseJson;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;

/**
 * 手机短信业务
 * Created by liuzhiwei on 2017/12/20.
 */
@Service
public class PhoneCodeServiceImpl implements PhoneCodeService {

    @Autowired
    private RatFWLogger logger;
    @Autowired
    private PhoneCodeMapper phoneCodeMapper;

    private static String ENCODING = "UTF-8";
    private static Random rnd = new Random();

    public ResponseJson sms(String phone) {

        // TODO Auto-generated method stub
        ResponseJson json = new ResponseJson();
        if (StringUtils.isEmpty(phone)) {
            json.setReturnCode(2);
            json.addResponseKeyValue("Phone Empty!");
            return json;
        }
        PhoneCode phoneCode = new PhoneCode();
        phoneCode.setCodePhoneCode(phone);
        phoneCode = phoneCodeMapper.getPhoneCode(phoneCode);
        if(phoneCode != null){
            if(phoneCode.getCodeSendTime().getTime() < new Date().getTime()+ 60000
                    && phoneCode.getCodeSendTime().getTime() > new Date().getTime() - 60000){
                json.setReturnCode(3);
                json.addResponseKeyValue("60秒内只能申请一次验证码");
                return json;
            }
        }

        // 获取验证码
        String code = getRandomCode(4);
        json = sendCMS(phone, code);
        if (json.getReturnCode() != 200) {
            json = sendCMS(phone, code);
        }
        //添加验证码到数据库
        PhoneCode addPhoneCode = new PhoneCode();
        addPhoneCode.setCodeTel(phone);
        addPhoneCode.setCodePhoneCode(code);
        if(phoneCode == null){
            phoneCodeMapper.addPhoneCode(addPhoneCode);
        }else{
            addPhoneCode.setCodeId(phoneCode.getCodeId());
            phoneCodeMapper.updatePhoneCode(addPhoneCode);
        }
        return json;
    }

    /**
     * 发送短信验证码 封装返回前台参数
     * @param phone		手机号码
     * @param code		短信验证码
     * @return
     */
    private ResponseJson sendCMS(String phone, String code) {
        ResponseJson json = new ResponseJson();
        json.setReturnCode(500);
        String result = null;
        try {
            String text = MessageFormat.format(ImberryConfig.INTER_SMS_TEXT, code);
            result = sendOtherCMS(phone, text);
        } catch (Exception e) {
            logger.info(PhoneCodeServiceImpl.class, e.getMessage());
            result = "验证码发送失败，请稍后重试";
        }
        if (StringUtils.equals(result, "SUCCESS")) {
            json.setReturnCode(200);
        }
        json.addResponseKeyValue(result);
        return json;
    }

    /**
     * 向指定手机发送短信 返回发送结果
     * @param phone	电话
     * @param text	短信内容
     * @return
     */
    private String sendOtherCMS(String phone, String text) {
        String results = sendSms(text,phone);
        logger.info("向手机：" + phone + ",发送短信：" + text + ",返回结果-->>" + results);
        JSONObject json =  JSONObject.fromObject(results);
        String resultcod  = json.get("code").toString();
        if("0".equals(resultcod)){
            return "SUCCESS";
        }else{
            return "验证码发送失败，请稍后重试";
        }
    }

    /**
     * 配置云片相关信息并发送请求
     * @param text		发送的内容
     * @param mobile	手机号
     * @return
     */
    public static String sendSms(String text, String mobile)  {
        Map<String, String> params = new HashMap<String, String>();
        params.put("apikey", ImberryConfig.INTER_SMS_KEY);
        params.put("text", text);
        params.put("mobile", mobile);
        return post(ImberryConfig.INTER_SMS_URL, params);
    }

    /** 基于HttpClient 4.3的通用POST方法
     * @param url       提交的URL
     * @param paramsMap 提交<参数，值>Map
     * @return 提交响应
     */
    public static String post(String url, Map<String, String> paramsMap) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        try {
            HttpPost method = new HttpPost(url);
            if (paramsMap != null) {
                List<NameValuePair> paramList = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> param : paramsMap.entrySet()) {
                    NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
                    paramList.add(pair);
                }
                method.setEntity(new UrlEncodedFormEntity(paramList, ENCODING));
            }
            response = client.execute(method);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                responseText = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }

    @Override
    public ResponseJson validCode(String phone, String code) {
        ResponseJson json = new ResponseJson();
        PhoneCode phoneCode = new PhoneCode();
        phoneCode.setCodeTel(phone);
        //根据手机号码获取验证码
        phoneCode = phoneCodeMapper.getPhoneCode(phoneCode);
        // 校验
        if (phoneCode == null) {
            // 操作有误
            json.setReturnCode(404);
            json.addResponseKeyValue("验证失败");
            return json;
        }
        Date now = new Date();
        if (now.getTime() >= (phoneCode.getCodeSendTime().getTime() + 180000)) {
            // 验证码无效
            json.setReturnCode(404);
            json.addResponseKeyValue("验证码无效");
            return json;
        }
        // 必须 验证码正确，并且场景正确
        if (!code.equals(phoneCode.getCodePhoneCode())) {
            // 验证码错误
            json.setReturnCode(404);
            json.addResponseKeyValue("验证码错误");
            return json;
        }
        // 只要校验，表示本次验证码使用
        json.setReturnCode(200);
        json.addResponseKeyValue("SUCCESS");
        return json;
    }

    public static String getRandomCode(int len) {
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++)
            sb.append("0123456789".charAt(rnd.nextInt("0123456789".length())));
        return sb.toString();
    }
}
