package com.bohuikeji.delivery.backstage.controller.api.customer;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bohuikeji.delivery.backstage.entity.*;
import com.bohuikeji.delivery.backstage.listener.order.OrderCreateListener;
import com.bohuikeji.delivery.backstage.listener.order.OrderDelayCancelListener;
import com.bohuikeji.delivery.backstage.service.*;
import com.bohuikeji.delivery.backstage.service.third.ThirdUtils;
import com.bohuikeji.delivery.backstage.util.PhoneUtils;
import com.bohuikeji.frame.module.admin.base.ApiController;
import com.bohuikeji.frame.module.admin.component.MqTool;
import com.bohuikeji.frame.module.admin.component.RedisUtil;
import com.bohuikeji.frame.module.admin.entity.back.APIEntity;
import com.bohuikeji.frame.module.admin.entity.sys.SysConfig;
import com.bohuikeji.frame.module.admin.entity.sys.SysError;
import com.bohuikeji.frame.module.admin.entity.vo.AddressVo;
import com.bohuikeji.frame.module.admin.service.ISysConfigService;
import com.bohuikeji.frame.module.admin.service.ITFranchiseeInformationService;
import com.bohuikeji.frame.module.admin.utils.*;
import com.bohuikeji.frame.module.admin.utils.wx.WxUtils;
import com.google.common.primitives.Ints;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import jodd.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;


/**
 * @author zhouliwu
 * 客户相关接口
 */
@Slf4j
@Api(tags = {"客户相关接口"})
@RestController
@RequestMapping("/api/customer")
public class CustomerApi extends ApiController {
    @Autowired
    ITCustomerService customerService;
    @Autowired
    ITOrderService orderService;
    @Autowired
    ITCustomerWalletService customerWalletService;
    @Autowired
    ITCustomerAddressService itCustomerAddressService;
    @Autowired
    ISysConfigService sysConfigService;
    @Autowired
    ITCourierService courierService;
    @Autowired
    IWxUserService wxUserService;
    @Autowired
    ITNewsService newsService;
    @Autowired
    MqTool mqTool;
    @Autowired
    IGmsService gmsService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    ITFranchiseeInformationService informationService;

    /**
     *
     * 客户获取接单派送员
     * @return
     */
    @ApiOperation("客户获取接单派送员")
    @GetMapping("/getTcourier")
    public APIEntity getTcourier(int[] courierIds){
        List<TCourier> tCouriers = new ArrayList<TCourier>();
        for(int i=0;i<courierIds.length;i++){
          TCourier tCourier = courierService.getOne(new QueryWrapper<TCourier>().eq("courier_id",courierIds[i]));
            tCouriers.add(tCourier);
        }
        return APIEntity.success(tCouriers);
    }

    /**
     * 根据客户的id获取当前客户的全部地址
     * @param id
     * @return
     */
    @ApiOperation(value = "根据经纬度获取所在城市",notes = "根据经纬度获取所在城市")
    @GetMapping("/getaddressCity")
    @ApiImplicitParams({
            @ApiImplicitParam(name="type",value="地址类型(寄件地址/收件地址)",dataType="String", paramType = "query",example="寄件地址",required=true)})
    public APIEntity getaddressCity(@RequestAttribute("JwtUserId") Integer id,String location){
        AddressVo addressVo = MapUtils.getAddressReGeo(location);
        if(addressVo == null){
            return APIEntity.fail("无法定位当前地址，请查看是否开启位置权限！");
        }
        TCustomer customer = customerService.getById(id);
        if(customer == null){
            return APIEntity.fail("当前账号不存在请重新登陆！");
        }
        Integer franId = informationService.checkPio(addressVo).getFranId();
        customerService.updateById(customer.setFranId(franId));
        return APIEntity.success(addressVo.getCity());
    }

    /**
     * 根据客户的id获取当前客户的全部地址
     * @param id
     * @return
     */
    @ApiOperation(value = "查询客户全部地址列表",notes = "查询寄件地址/收件地址/全部地址")
    @GetMapping("/getAddressAll")
    @ApiImplicitParams({
            @ApiImplicitParam(name="type",value="地址类型(寄件地址/收件地址)",dataType="String", paramType = "query",example="寄件地址",required=true)})
    public APIEntity<List<TCustomerAddress>> addressList(@RequestAttribute("JwtUserId") Integer id,String type){
        QueryWrapper<TCustomerAddress> qu=new QueryWrapper<TCustomerAddress>().eq("customer_id",id).last(" limit 5");
        if(StringUtils.isBlank(type)){
            return APIEntity.success(itCustomerAddressService.list(qu.orderByDesc("cust_add_id")));
        }
        return APIEntity.success(itCustomerAddressService.list(qu.eq("type",type).orderByDesc("cust_add_id")));
    }

    /**
     * 获取默认地址
     * @return
     */
    @ApiOperation("获取默认地址")
    @GetMapping("/getdefault")
    public APIEntity<TCustomerAddress> getDefault(@RequestAttribute("JwtUserId") Integer id){
            return APIEntity.success(itCustomerAddressService.getOne(new QueryWrapper<TCustomerAddress>().eq("customer_id",id).eq("type","寄件地址").eq("default_address",1),false));

    }




    /**
     * 客户App注册/验证码登陆
     * @return
     */
    @ApiOperation("客户App注册/验证码登陆")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="客户手机号",dataType="String", paramType = "query",example="15771331234",required=true),
            @ApiImplicitParam(name="verCode",value="短信验证码",dataType="String", paramType = "query",example="",required=true)})
    @PostMapping("/login/register")
    public APIEntity loginRegister(String customerPhone,String verCode,@RequestHeader String token,String cid){
        Object code = redisUtil.get("gms:customer:"+customerPhone);
        if(code==null){
            return APIEntity.fail("验证码无效，请重新获取！");
        }
        if("15771335697".equals(customerPhone)){
            if(!"000000".equals(verCode)){
                return APIEntity.fail("验证码错误！");
            }
        }
        else {
            if (!code.toString().equals(verCode)){
                return APIEntity.fail("验证码错误！");
            }
        }
        TCustomer customer= customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",customerPhone),false);
        TCustomer tCustomer = new TCustomer();
        // 清理使用过的token
        redisUtil.del(token);
        if(customer != null) {
            if("微信用户".equals(customer.getCustomerName())){
                String num=NumberUtils.getShort();
                customer.setCustomerName("客户"+num);
                customer.setCid(cid);
                customerService.updateById(customer);
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("customerId",customer.getCustomerId());
            jsonObject.put("customerPhone",customer.getCustomerPhone());
            jsonObject.put("token",JwtTokenUtil.createToken("客户",customer.getCustomerId()));
            jsonObject.put("isType",customer.getIsType());
            customerService.updateById(customer.setCid(cid));
            return APIEntity.success(jsonObject);
        }else {
            String num=NumberUtils.getShort();
            tCustomer.setCustomerName("客户"+num);
            tCustomer.setCustomerPhone(customerPhone);
            tCustomer.setCustomerPwd("000000");
            tCustomer.setCustomerStatus("已激活");
            //tCustomer.setRegistratMeth("APP");
            tCustomer.setCid(cid);
            tCustomer.setCreateTime(LocalDateTime.now());
            tCustomer.setUpdateTime(LocalDateTime.now());
            if (!customerService.save(tCustomer)) {
                log.error("派送员注册失败，创建失败，派送员：" + tCustomer);
                return APIEntity.fail("系统繁忙，请稍后重试！");
            }
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("customerId",tCustomer.getCustomerId());
        jsonObject.put("customerPhone",tCustomer.getCustomerPhone());
        jsonObject.put("token",JwtTokenUtil.createToken("客户",tCustomer.getCustomerId()));
        jsonObject.put("isType",tCustomer.getIsType());
        return APIEntity.success(jsonObject);
    }

    /**
     *微信小程序绑定手机号
     * @return
     */
    @ApiOperation("微信小程序绑定手机号")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="客户手机号",dataType="String", paramType = "query",example="15500000000",required=true)})
    @GetMapping("/bind/phone")
    public APIEntity bindPhone(@RequestAttribute("JwtUserId") Integer id,String customerPhone){
        TCustomer customer = customerService.getById(id);
        if(customer==null){
            return APIEntity.fail("账户信息不存在，请重新登陆！");
        }
        if(StringUtils.isNotBlank(customer.getCustomerPhone())){
            return APIEntity.fail("手机号已绑定，请不要重复绑定！");
        }
        if(StringUtils.isBlank(customerPhone)){
            return APIEntity.fail("手机号不能为空");
        }
        if("15295598596".equals(customerPhone)){
            return APIEntity.fail("该账户已注销");
        }
        customerService.updateById(customer.setCustomerPhone(customerPhone));
        return APIEntity.success("绑定成功");
    }

    /**
     *客户App获取验证码
     * @return
     */
    @ApiOperation("客户App获取验证码(手机号、验证码登陆）")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="客户手机号",dataType="String", paramType = "query",example="15500000000",required=true)})
    @GetMapping("/getVerCode")
    public APIEntity getVerCode(String customerPhone,HttpServletRequest request){
        if(StringUtils.isBlank(customerPhone)){
            return APIEntity.fail("手机号不能为空");
        }
        if("15295598596".equals(customerPhone)){
            return APIEntity.fail("该账户已注销");
        }
        String code=gmsService.sendCode(customerPhone,request);
        //10分钟有效
        redisUtil.set("gms:customer:"+customerPhone,code,60*10);
        return APIEntity.success(code);
    }

    /**
     * 客户授权登陆
     * @return
     */
    @ApiOperation("客户授权登陆（暂未接通）")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="客户手机号",dataType="String", paramType = "query",example="15771331234",required=true),
            @ApiImplicitParam(name="verCode",value="短信验证码",dataType="String", paramType = "query",example="",required=true),
            @ApiImplicitParam(name="grantCode",value="各端授权code",dataType="String", paramType = "query",example="",required=true),
            @ApiImplicitParam(name="loginType",value="各端登陆类型",dataType="String", paramType = "query",example="",required=true),
            @ApiImplicitParam(name="registratMeth",value="各端登陆类型书名",dataType="String", paramType = "query",example="",required=true)})
    @PostMapping("/login/grant/code/phone")
    public APIEntity customerLog(String customerPhone,String verCode,String grantCode,String loginType,String registratMeth,@RequestHeader String token,String cid) throws AlipayApiException {
        Object code = redisUtil.get("gms:customer:"+customerPhone);
        if(code==null){
            return APIEntity.fail("验证码无效，请重新获取！");
        }
        if (!code.toString().equals(verCode)){
            return APIEntity.fail("验证码错误！");
        }
        TCustomer customer= customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",customerPhone),false);
        // 清理使用过的token
        redisUtil.del(token);
        if(customer != null) {
            if("微信用户".equals(customer.getCustomerName())){
                String num=NumberUtils.getShort();
                customer.setCustomerName("客户"+num);
                customer.setCid(cid);
                customerService.updateById(customer);
            }
        }else {
            customer = customerService.savecodeCustomer(registratMeth,loginType);
        }
        wxUserService.saveCusOrWxUser(grantCode,loginType,customer);//账号绑定授权openId
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("customerId",customer.getCustomerId());
        jsonObject.put("customerPhone",customer.getCustomerPhone());
        jsonObject.put("token",JwtTokenUtil.createToken("客户",customer.getCustomerId()));
        return APIEntity.success(jsonObject);
    }

    /**
     *微信授权登陆
     * @return
     */
    @ApiOperation("微信授权登陆")
    @ApiImplicitParams({
            @ApiImplicitParam(name="code",value="登陆凭证",dataType="String", paramType = "query",example="vxxxxxxxxxxxxxxxxz",required=true)})
    @PostMapping("/wx/code/login")
    public APIEntity wxlogin(String code) throws Exception {
        String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session?";
        Map<String, String> param = new HashMap<>();
        param.put("appid", "wxcf3a1f3166d803a9");
        param.put("secret", "bb03f68922307171da460f6320f8f9f4");
        param.put("js_code", code);
        param.put("grant_type", "authorization_code");
        // 发送请求
        JSONObject jsonObject = JSONObject.parseObject(HttpRequest.get(WX_LOGIN_URL).query(param).send().bodyText());
        SysError.saveError("[外键关联数据丢失]执行sql：{0}，参数：{1}",jsonObject,"授权登陆");
        if(jsonObject ==null){
            return APIEntity.success("微信登陆失败！");
        }
        // 获取参数返回的
        String sessionKey = jsonObject.get("session_key").toString();
        String openId = jsonObject.get("openid").toString();
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("open_id",openId),false);
        if(customer ==null){
            customer = customerService.saveCustomer("微信小程序");
        }
        if("微信用户".equals(customer.getCustomerName())){
            String num=NumberUtils.getShort();
            customer.setCustomerName("客户"+num);
        }
        customer.setOpenId(openId);
        customer.setSessionKey(sessionKey);
        customer.setUpdateTime(LocalDateTime.now());
        customerService.updateById(customer);
        JSONObject cusJosn = new JSONObject();
        cusJosn.put("customerId",customer.getCustomerId());
        cusJosn.put("customerPhone","");
        cusJosn.put("token",JwtTokenUtil.createToken("客户",customer.getCustomerId()));
        cusJosn.put("isType",customer.getIsType());
        return APIEntity.success(cusJosn);
    }


    /**
     *客户微信手机号登陆登陆
     * @return
     */
    @ApiOperation("客户微信手机号登陆登陆")
    @ApiImplicitParams({
            @ApiImplicitParam(name="code",value="登陆凭证",dataType="String", paramType = "query",example="vxxxxxxxxxxxxxxxxz",required=true)})
    @PostMapping("/wxLogin")
    public APIEntity wxPhoneLogin(String code) throws Exception {
        String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session?";
        Map<String, String> param = new HashMap<>();
        param.put("appid", "wxcf3a1f3166d803a9");
        param.put("secret", "bb03f68922307171da460f6320f8f9f4");
        param.put("js_code", code);
        param.put("grant_type", "authorization_code");
        // 发送请求
        JSONObject jsonObject = JSONObject.parseObject(HttpRequest.get(WX_LOGIN_URL).query(param).send().bodyText());
        SysError.saveError("[外键关联数据丢失]执行sql：{0}，参数：{1}",jsonObject,"手机号登陆");
        if(jsonObject ==null){
            return APIEntity.success("微信登陆失败！");
        }
        // 获取参数返回的
        String sessionKey = jsonObject.get("session_key").toString();
        String openId = jsonObject.get("openid").toString();
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("open_id",openId),false);
        if(customer ==null){
            customer = customerService.saveCustomer("微信小程序");
        }
        if("微信用户".equals(customer.getCustomerName())){
            String num=NumberUtils.getShort();
            customer.setCustomerName("客户"+num);
        }
        customer.setOpenId(openId);
        customer.setSessionKey(sessionKey);
        customer.setUpdateTime(LocalDateTime.now());
        customerService.updateById(customer);
        return APIEntity.success(JwtTokenUtil.createToken("客户",customer.getCustomerId()));
}


    /**
     * 客户微信小程序登陆按用户解密
     * @param id token
     * @param encryptedData 加密数据
     * @param iv 初始向量
     * @return
     */
    @ApiOperation("客户微信小程序登陆按用户解密")
    @ApiImplicitParams({
            @ApiImplicitParam(name="encryptedData",value="包括敏感数据在内的完整用户信息的加密数据",dataType="String", paramType = "query",example="vxxxxxxxxxxxxxxxxz",required=true),
            @ApiImplicitParam(name="iv",value="加密算法的初始向量",dataType="String", paramType = "query",example="vxxxxxxxxxxxxxxxxz",required=true)})
    @PostMapping("/wxAesUser")
    public APIEntity decodeUserInfo(@RequestAttribute("JwtUserId") Integer id,String encryptedData, String iv) {
        log.info("@@@@@@@@@客户端吧微信小程序信息解密---2");
        JSONObject jsonObject = new JSONObject();
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_id",id));
        if(customer==null){
            return APIEntity.fail("无法识别用户信息").setStatus(412);
        }
        //获取微信用户信息
        JSONObject wxUserInfoJson= WxUtils.getUserInfo(encryptedData,customer.getSessionKey(),iv);
        if(wxUserInfoJson==null){
            log.error("更新用户信息失败，用户:[{}],ID=[{}]，未授权",customer.getCustomerName(),customer.getCustomerId());
            return APIEntity.success(customer);
        }
        if(wxUserInfoJson.getString("phoneNumber").equals(customer.getCustomerPhone())){
            jsonObject.put("customerId",customer.getCustomerId());
            jsonObject.put("customerPhone",customer.getCustomerPhone());
            jsonObject.put("token",JwtTokenUtil.createToken("客户",customer.getCustomerId()));
            jsonObject.put("isType",customer.getIsType());
            return APIEntity.success(jsonObject);
        }
        TCustomer tCustomer = customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",wxUserInfoJson.getString("phoneNumber")));//旧的相同手机号账户
        log.error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@数据库的新用户：[{}]",id);
        log.error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@数据库的旧用户：[{}]",customer.getCustomerId());
        if(tCustomer != null){
            tCustomer.setCustomerPhone(wxUserInfoJson.getString("phoneNumber"));
            tCustomer.setUpdateTime(LocalDateTime.now());
            tCustomer.setOpenId(customer.getOpenId());
            tCustomer.setSessionKey(customer.getSessionKey());
            customerService.updateById(tCustomer);
            jsonObject.put("customerId",tCustomer.getCustomerId());
            jsonObject.put("customerPhone",tCustomer.getCustomerPhone());
            jsonObject.put("token",JwtTokenUtil.createToken("客户",tCustomer.getCustomerId()));
            //customerService.removeById(customer);
        }else {
            customer.setCustomerPhone(wxUserInfoJson.getString("phoneNumber"));
            customer.setUpdateTime(LocalDateTime.now());
            customerService.updateById(customer);
            jsonObject.put("customerId",customer.getCustomerId());
            jsonObject.put("customerPhone",customer.getCustomerPhone());
            jsonObject.put("token",JwtTokenUtil.createToken("客户",customer.getCustomerId()));
            jsonObject.put("isType",customer.getIsType());
        }
        return APIEntity.success(jsonObject);
    }

    /**
     * 客户App手机号一键登录
     * @param customerPhone
     * @param request
     * @return
     */
    @ApiOperation("客户App手机号一键登录")
    @GetMapping(value="/one/click/login")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="手机号",dataType="string", paramType = "query",example="15771335697",required = true)})
    public APIEntity oneClickLogin(String customerPhone,HttpServletRequest request){
        TCustomer customer =customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",customerPhone));
        if (customer==null){
            return APIEntity.fail("手机号未注册，无法登陆！");
        }
        return APIEntity.success(JwtTokenUtil.createToken("客户",customer.getCustomerId()));
    }

    /**
     * 客户App密码登录
     * @param customerPhone
     * @param customerPwd
     * @param request
     * @returnzhang'j'ao
     */
    @ApiOperation("客户App登录")
    @GetMapping(value="/login/app")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="手机号",dataType="string", paramType = "query",example="15771335697",required = true),
            @ApiImplicitParam(name="customerPwd",value="密码",dataType="string", paramType = "query",example="123456",required = true)})
    public APIEntity phoneByPwdLogin(String customerPhone, String customerPwd, HttpServletRequest request){
        TCustomer customer =customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",customerPhone).eq("customer_pwd",customerPwd));
        if (customer==null){
            return APIEntity.fail("手机号或密码错误或该用户未注册！");
        }
        return APIEntity.success(JwtTokenUtil.createToken("客户",customer.getCustomerId()));
    }


    /**
     * 客户App注册
     * @param customerPhone
     * @param customerPwd
     * @param verCode
     * @param customerType
     * @param cid
     * @return
     */
    @ApiOperation("客户App注册")
    @GetMapping(value="/login/register")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="手机号",dataType="string", paramType = "query",example="15771335697",required = true),
            @ApiImplicitParam(name="customerPwd",value="密码",dataType="string", paramType = "query",example="123456",required = true),
            @ApiImplicitParam(name="verCode",value="验证码",dataType="string", paramType = "query",example="025645",required = true),
            @ApiImplicitParam(name="customerType",value="用户类型",dataType="string", paramType = "query",example="个人",required = true),
            @ApiImplicitParam(name="cid",value="设备id",dataType="string", paramType = "query",example="1fdrewf4sf454fs5f45f")})
    public APIEntity register(String customerPhone, String customerPwd,String verCode,String customerType,String cid){
        Object code = redisUtil.get("gms:customer:"+customerPhone);
        if(code==null){
            return APIEntity.fail("验证码无效，请重新获取！");
        }
        if("15771335697".equals(customerPhone)){
            if(!"000000".equals(verCode)){
                return APIEntity.fail("验证码错误！");
            }
        }
        else {
            if (!code.toString().equals(verCode)){
                return APIEntity.fail("验证码错误！");
            }
        }
        TCustomer customer =customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",customerPhone).eq("customer_pwd",customerPwd));
        TCustomer tCustomer = new TCustomer();
        if(customer != null) {
            if("微信用户".equals(customer.getCustomerName())){
                String num=NumberUtils.getShort();
                customer.setCustomerName("客户"+num);
                customer.setCid(cid);
                customer.setCustomerType(customerType);
                customerService.updateById(customer);
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("customerId",customer.getCustomerId());
            jsonObject.put("customerPhone",customer.getCustomerPhone());
            jsonObject.put("token",JwtTokenUtil.createToken("客户",customer.getCustomerId()));
            jsonObject.put("isType",customer.getIsType());
            customerService.updateById(customer.setCid(cid));
            return APIEntity.success(jsonObject);
        }else {
            String num=NumberUtils.getShort();
            tCustomer.setCustomerName("客户"+num);
            tCustomer.setCustomerPhone(customerPhone);
            tCustomer.setCustomerPwd("000000");
            tCustomer.setCustomerStatus("已激活");
            customer.setCustomerType(customerType);
            tCustomer.setCid(cid);
            tCustomer.setCreateTime(LocalDateTime.now());
            tCustomer.setUpdateTime(LocalDateTime.now());
            if (!customerService.save(tCustomer)) {
                log.error("派送员注册失败，创建失败，派送员：" + tCustomer);
                return APIEntity.fail("系统繁忙，请稍后重试！");
            }
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("customerId",tCustomer.getCustomerId());
        jsonObject.put("customerPhone",tCustomer.getCustomerPhone());
        jsonObject.put("token",JwtTokenUtil.createToken("客户",tCustomer.getCustomerId()));
        jsonObject.put("isType",customer.getIsType());
        return APIEntity.success(jsonObject);
    }

    /**
     * 客户微信小程序登陆获取用户信息
     * 获取微信登陆用户信息/并更改原来的用户名
     * @param id
     * @param nickname
     * @return
     */
    @ApiOperation("客户微信小程序登陆获取用户信息")

    @ApiImplicitParams({
            @ApiImplicitParam(name="nickname",value="包括敏感数据在内的完整用户信息的加密数据",dataType="String", paramType = "query",example="xxx")})
    @PostMapping("/wxSetUserName")
    public APIEntity setuserName(@RequestAttribute("JwtUserId") Integer id,String nickname){
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().eq("customer_id",id));
        if("微信用户".equals(nickname)){
            String num=NumberUtils.getShort();
            customer.setCustomerName("客户"+num);
        }else {
            customer.setCustomerName(nickname);
        }
        customerService.updateById(customer);
        return APIEntity.success(customer);
    }

    /**
     * 验证旧手机号验证码
     * @param id
     * @return
     */
    @ApiOperation("验证旧手机号验证码")
    @GetMapping("/check/code")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="手机号",dataType="string", paramType = "query",example="15540709945",required = true),
            @ApiImplicitParam(name="verCode",value="验证码",dataType="string", paramType = "query",example="025645",required = true)})
    public APIEntity checkCode(@RequestAttribute("JwtUserId") Integer id,String customerPhone,String verCode) {
        Object code = redisUtil.get("gms:customer:"+customerPhone);
        if(code==null){
            return APIEntity.fail("验证码无效，请重新获取！");
        }
        if (!code.toString().equals(verCode)){
            return APIEntity.fail("验证码错误！");
        }
        return APIEntity.success("验证成功");
    }

    /**
     * 验证旧手机号是否已注册
     * @param id
     * @return
     */
    @ApiOperation("验证旧手机号是否已注册")
    @GetMapping("/check/repeat")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="手机号",dataType="string", paramType = "query",example="15540709945",required = true)})
    public APIEntity checkRepeat(@RequestAttribute("JwtUserId") Integer id,String customerPhone) {
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_phone",customerPhone));
        if(customer !=null){
            return APIEntity.fail("手机号已存在");
        }
        return APIEntity.success("验证成功");
    }

    /**
     * 设置推送是否开启
     * @param id
     * @return
     */
    @ApiOperation("设置推送是否开启")
    @GetMapping("/set/push/not")
    @ApiImplicitParams({
            @ApiImplicitParam(name="type",value="手机号",dataType="Boolean", paramType = "query",example="15540709945",required = true)})
    public APIEntity setPushOrNot(@RequestAttribute("JwtUserId") Integer id,boolean type) {
        TCustomer customer = customerService.getById(id);
        if(customer ==null){
            return APIEntity.fail("该用户不存在，请重新登陆！");
        }
        customer.setPushOrNot(type);
        customerService.updateById(customer);
        return APIEntity.success("设置成功");
    }

    /**
     * 修改客户手机号
     * 优惠卷
     * 钱包
     * 商户信息
     * @param id
     * @return
     */
    @ApiOperation("修改客户手机号")
    @PostMapping("/update/phone")
    @ApiImplicitParams({
            @ApiImplicitParam(name="customerPhone",value="手机号",dataType="string", paramType = "query",example="15771335697",required = true),
            @ApiImplicitParam(name="verCode",value="验证码",dataType="string", paramType = "query",example="025645",required = true)})
    public APIEntity updatePhone(@RequestAttribute("JwtUserId") Integer id,String customerPhone,String verCode) {
        Object code = redisUtil.get("gms:customer:"+customerPhone);
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().notIn("customer_status","已注销").eq("customer_id",id));
        if(customer ==null){
            return APIEntity.fail("改账户信息不存在");
        }
        if(code==null){
            return APIEntity.fail("验证码无效，请重新获取！");
        }
        if (!code.toString().equals(verCode)){
            return APIEntity.fail("验证码错误！");
        }
        customer.setCustomerPhone(customerPhone);
        customer.setUpdateTime(LocalDateTime.now());
        customerService.updateById(customer);
        return APIEntity.success("修改成功");
    }


    /**
     * 客户App注销
     * 优惠卷
     * 钱包
     * 商户信息
     * @param id
     * @return
     */
    @ApiOperation("客户App注销")
    @PostMapping("/logout")
    public APIEntity logout(@RequestAttribute("JwtUserId") Integer id) {
        TCustomer customer = customerService.getOne(new QueryWrapper<TCustomer>().eq("customer_id",id));
        if(customer==null){
            return APIEntity.fail("无法识别用户信息").setStatus(412);
        }
        if("已注销".equals(customer.getCustomerStatus())){
            return APIEntity.fail("您的账户已注销，请不要重复提交！");
        }
        if(orderService.list(new QueryWrapper<TOrder>().eq("player_id",customer.getCustomerId()).notIn("order_status","已完成","已取消","已退款")).size()>0){
            return APIEntity.fail("您有订单正在派送中，请完成订单后再注销！");
        }
        TCustomerWallet customerWallet = customerWalletService.getOne(new QueryWrapper<TCustomerWallet>().eq("customer_id",customer.getCustomerId()));
        if(customerWallet != null && customerWallet.getWalletPrice().compareTo(BigDecimal.ZERO) > 0 || customerWallet != null && customerWallet.getRefuntPrice().compareTo(BigDecimal.ZERO) > 0){
            return APIEntity.fail("您的钱包中有余额未提现，请确认余额到账后在注销！");
        }
        customer.setCustomerStatus("已注销");
        customer.setUpdateTime(LocalDateTime.now());
        customerService.updateById(customer);
        return APIEntity.success("注销成功");
    }

    /**
     * 获取客户登陆信息
     * @return
     */
    @ApiOperation("获取客户登陆信息")
    @GetMapping("/get")
    public APIEntity<TCustomer> getById(@RequestAttribute("JwtUserId") Integer id){
        return APIEntity.success(customerService.getById(id));
    }

    /**
     * （仅测试可用）获取客户token
     * @return
     */
    @ApiOperation("【仅供测试使用】获取客户Token信息")
    @GetMapping("/test/token")
    public APIEntity getToken(String phone){
        return APIEntity.success(
                JwtTokenUtil.createToken("客户",
                        customerService.getOne(new QueryWrapper<TCustomer>()
                                .eq("customer_phone",phone),false).getCustomerId()));
    }

    /**
     * 修改用户
     * @return
     */
    @ApiOperation("选择用户类型")
    @GetMapping("/update/type")
    public APIEntity<TCustomer> updateCustType(@ApiIgnore("id") @RequestAttribute("JwtUserId") Integer id, String customerType){
        TCustomer tCustomer = customerService.getById(id);
        tCustomer.setCustomerType(customerType);
        tCustomer.setIsType(true);
        customerService.updateById(tCustomer);
        return APIEntity.success();
    }

    /**
     * 修改用户
     * @return
     */
    @ApiOperation("修改用户")
    @GetMapping("/update/cust")

    public APIEntity<TCustomer> updateCust(@RequestAttribute("JwtUserId") Integer id,String customerName){
        TCustomer tCustomer = customerService.getById(id);
        tCustomer.setCustomerName(customerName);
        customerService.updateById(tCustomer);
        return APIEntity.success(tCustomer);
    }

    /**
     * 客户下单
     * @param order
     * @return
     */
    @ApiOperation("客户App下单")
    @PostMapping("/place/order")
    @ApiImplicitParams({})
    public APIEntity insertOrder(@RequestBody TOrder order) {
        if(redisUtil.get("order_id_"+order.getPlayerId())!=null){
            return APIEntity.success();
        }
        redisUtil.set("order_id_"+order.getPlayerId(),order,5);
        order.setOrderChannel("微信小程序");
        Boolean bool = orderService.saveplace(order);
        if(bool){
            //初始化完成的订单放入Redis
            redisUtil.set("order:create:num:"+order.getOrderNum(),order,15);
            //发送订单创建完成通知
            mqTool.sendMsg(order.getOrderNum(), OrderCreateListener.class);
            //自动取消时间，有加盟商30分钟，无加盟商20分钟
            Duration time=Duration.ofMinutes(order.getFranId().equals(1)?10:30);
            //订单延时取消
            mqTool.sendDelayMsg(order.getOrderNum(), OrderDelayCancelListener.class,time);
        }
        return APIEntity.success(0);
    }


    /**
     * 下单预算金额
     * @param order
     * @return
     */
    @ApiOperation("客户App下单预算金额")
    @PostMapping("/place/estimate")
    public APIEntity estimate(@RequestBody TOrder order) {
        try {
            order = orderService.moneySumNew(order);
        }catch (NullPointerException e){
            //log.error("下单金额计算失败，订单参数错误：[{}]",order);
        }
        JSONObject json=new JSONObject();
        json.put("monSum",order.getOrderExpectPrice().setScale(2,BigDecimal.ROUND_HALF_UP));
        json.put("distance",order.getOrderDistance());
        log.info("【下单金额预估】订单：{}，返回：{}",order.getOrderNum(),json.toJSONString());
        return APIEntity.success(json);
    }
    /**
     * [新版接口]
     * 骑手APP计算并更新订单
     * @param order
     * @return
     */
    @ApiOperation("骑手APP计算并更新订单")
    @PostMapping("/place/estimate/courier")
    public APIEntity estimateCourier(@RequestBody TOrder order) {
        if("0".equals(order.getOrderBatchNum())){
            order = orderService.moneySumNew(order);
        }
        order.updateById();
        return APIEntity.success(order);
    }

    /**
     * 客户修改订单并计算差价
     * @param order
     * @return
     */
    @ApiOperation("客户修改订单并计算差价")
    @PostMapping("/modify/order/customer/price")
    public APIEntity modifyOrder(@RequestBody TOrder order) {
        if("0".equals(order.getOrderBatchNum())){
            order = orderService.initialOrder(order);
            log.info("订单金额计算结果：[{}]",order);
        }
        JSONObject json=new JSONObject();
        if(order.getOrderExpectPrice().compareTo(order.getOrderFactPrice()) < 1){
            json.put("priceDiff","0.00");
            json.put("distance",order.getOrderDistance());
        }else {
            json.put("priceDiff",order.getOrderExpectPrice().subtract(order.getOrderFactPrice()));
            json.put("distance",order.getOrderDistance());
        }
        return APIEntity.success(json);
    }



    /**
     * 客户App取消订单
     * @param orderId
     * @param customerId
     * @return
     */
    @ApiOperation("客户App取消订单")
    @PostMapping("/cancel/order")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderId",value="订单id",dataType="Integer", paramType = "query",example="1",required=true),
            @ApiImplicitParam(name="customerId",value="下单人id",dataType="Integer", paramType = "query",example="1",required=true)})
    public APIEntity cancel(String orderId,Integer customerId){
        TOrder tOrder = orderService.getOne(new QueryWrapper<TOrder>().eq("order_id",orderId).eq("player_id",customerId));
        if(!tOrder.getOrderStatus().equals(Constants.WAITING_FOR_ORDERS) && !tOrder.getOrderStatus().equals(Constants.WAITING_FOR_PICK)){
            return APIEntity.success("已超过规定取消时间");
        }
        if(tOrder.getOrderStatus().equals(Constants.WAITING_FOR_ORDERS)){
            tOrder.setOrderStatus("已取消");
            tOrder.setOrderEndTime(LocalDateTime.now());
            orderService.updateById(tOrder);
            ThirdUtils.orderCancel(tOrder);
            //根据订单状态修改订单流转状态
            TOrderCircu.insertCircu(tOrder);
            return APIEntity.success("订单取消成功");
        }
        if(tOrder.getOrderStatus().equals(Constants.WAITING_FOR_PICK)){
            //计算时间差
            Duration duration = Duration.between(tOrder.getAcceptanceTime(),LocalDateTime.now());
            SysConfig sysConfig = sysConfigService.getOne(new QueryWrapper<SysConfig>().eq("config_group","cancellation_time"));
            long shijian = Long.parseLong(sysConfig.getConfigValue());
            if(duration.toMinutes() == shijian || duration.toMinutes() < shijian){
                tOrder.setOrderStatus("已取消");
                tOrder.setOrderEndTime(LocalDateTime.now());
                orderService.updateById(tOrder);
                ThirdUtils.orderCancel(tOrder);
                //根据订单状态修改订单流转状态
                TOrderCircu.insertCircu(tOrder);
                newsService.pushCustomerMsg2(tOrder.getPlayerId(),"你好,你有订单已取消，请及时查看");
            }else {
                return APIEntity.success("已超过规定取消时间");
            }
        }
        return APIEntity.success(tOrder.getAcceptanceTime());
    }


    /**
     * 客户App新增地址
     * @param id
     * @param name
     * @param phone
     * @param address
     * @param location
     * @param isDefault
     * @return
     */
    @ApiOperation("客户新增或者修改客户地址接口")
    @PostMapping("/get/address/details")
    @ApiImplicitParams({
            @ApiImplicitParam(name="address",value="结构化地址文本",dataType="String", paramType = "query",example="内蒙古自治区呼和浩特市新城区成吉思汗大街29号",required=true)})
    public APIEntity addressDetails(@RequestAttribute("JwtUserId") Integer id,String address){
        if (StringUtils.isBlank(address)){
            return APIEntity.fail("参数错误：[address=null]");
        }
        AddressVo addressVo=MapUtils.getAddressGeo(address);
        //客户端上传经纬度则优先解析经纬度


        return APIEntity.success(addressVo);
    }
    /**
     * 客户App新增地址
     * @param id
     * @param name
     * @param phone
     * @param address
     * @param location
     * @param isDefault
     * @return
     */
    @ApiOperation("客户新增或者修改客户地址接口")
    @PostMapping("/address/saveOrUpdate")
    @ApiImplicitParams({
            @ApiImplicitParam(name="addressId",value="地址Id(新增地址则留空)",dataType="Integer", paramType = "query",example=" ",required=false),
            @ApiImplicitParam(name="name",value="姓名",dataType="String", paramType = "query",example="孙劲辉",required=true),
            @ApiImplicitParam(name="phone",value="电话",dataType="String", paramType = "query",example="15771335697",required=true),
            @ApiImplicitParam(name="address",value="结构化地址文本",dataType="String", paramType = "query",example="内蒙古自治区呼和浩特市新城区成吉思汗大街29号",required=true),
            @ApiImplicitParam(name="detail",value="详细地址",dataType="String", paramType = "query",example="1栋二单元1024(11楼左手第二间)",required=false),
            @ApiImplicitParam(name="isDefault",value="是否为默认地址(是填1，否填0)",dataType="Integer", paramType = "query",example="1",required=true),
            @ApiImplicitParam(name="location",value="经纬度",dataType="String", paramType = "query",example="111.78387,40.86792",required=true),
            @ApiImplicitParam(name="type",value="地址类型",dataType="String", paramType = "query",example="寄件地址/收件地址",required=true)})
    public APIEntity addAddress(@RequestAttribute("JwtUserId") Integer id,Integer addressId,String name,String phone,String address,String detail,String location,Boolean isDefault,String type){
        if(!StringUtils.isChinese(name)){
            return APIEntity.fail("姓名不合法，请输入真实姓名2-6个汉字");
        }
        /*if(!PhoneUtils.isVerify(phone)){
            return APIEntity.fail("手机号不合法！");
        }*/
        if (StringUtils.isBlank(address)){
            return APIEntity.fail("参数错误：[address=null]");
        }
        TCustomerAddress tCustomerAddress=new TCustomerAddress();
        if (addressId!=null){
            tCustomerAddress=itCustomerAddressService.getById(addressId);
            if (tCustomerAddress==null){
                log.error("未找到对应地址id=[{}]",addressId);
                throw new RuntimeException("未找到对应地址id="+addressId);
            }
        }
        if(StringUtils.isBlank(detail)){
            detail="";
        }
        AddressVo addressVo;
        //客户端上传经纬度则优先解析经纬度
        try {
            if (StringUtils.isNotBlank(location)){
                addressVo=MapUtils.getAddressReGeo(location);
            }
            else{
                addressVo=MapUtils.getAddressGeo(address+detail);
            }
        }catch (RuntimeException e){
            log.error("无法解析客户端地址信息",e);
            throw new RuntimeException("无法解析客户端地址信息");
        }
        addressVo.setAddress(address);
        addressVo.setDetail(detail);
        addressVo.setCityId("1001");
        tCustomerAddress.setName(name);
        tCustomerAddress.setPhone(phone);
        tCustomerAddress.setLocationAddress(address+detail);
        tCustomerAddress.setAddressJson(addressVo);
        tCustomerAddress.setCustomerId(id);
        tCustomerAddress.setDefaultAddress(isDefault);
        tCustomerAddress.setType(type);
        if (isDefault){
            itCustomerAddressService.update(new UpdateWrapper<TCustomerAddress>().set("default_address ",0).eq("type",type).eq("customer_id",id));
        }
        itCustomerAddressService.saveOrUpdate(tCustomerAddress);
        return APIEntity.success(tCustomerAddress);
    }
    /**
     * 客户App删除地址
     * @param custAddId
     * @return
     */
    @ApiOperation("客户App删除地址")
    @PostMapping("/del/address")
    @ApiImplicitParams({
            @ApiImplicitParam(name="custAddId",value="要删除的地址id",dataType="Integer", paramType = "query",example="1",required=true)})
    public APIEntity delAdress(Integer custAddId){
        System.out.println("custAddId:"+custAddId);
        return APIEntity.success(itCustomerAddressService.removeById(custAddId));
    }
    /**
     * 按ID批量删除地址
     * @param custAddIds
     * @return
     */
    @ApiOperation(value="按ID批量删除地址")
    @PostMapping("/deleteBatch")
    @ApiImplicitParams({
            @ApiImplicitParam(name="custAddIds",value="删除的地址id组",dataType="int[]", paramType = "query",example="1,2,3",required=true)})
    public APIEntity deleteBatch(int[] custAddIds){
        return  APIEntity.success(itCustomerAddressService.removeByIds(Ints.asList(custAddIds)));
    }
    /**
     * 客户根据经纬度查询地址
     * @param id
     * @param location
     * @return
     */
    @ApiOperation("客户根据经纬度查询地址")
    @PostMapping("/get/address/latlog")
    @ApiImplicitParams({
            @ApiImplicitParam(name="location",value="结构化地址文本",dataType="String", paramType = "query",example="111.665534,40.858344",required=true)})
    public APIEntity addressDetailsLatLog(@RequestAttribute("JwtUserId") Integer id,String location){
        if (StringUtils.isBlank(location)){
            return APIEntity.fail("参数错误：[location=null]");
        }
        AddressVo addressVo=MapUtils.getAddressReGeo(location);
        //客户端上传经纬度则优先解析经纬度
        return APIEntity.success(addressVo);
    }

    /**
     * 客户根据经纬度查询城市
     * @param id
     * @param location
     * @return
     */
    @ApiOperation("客户根据经纬度查询城市")
    @GetMapping("/get/city/latlon")
    @ApiImplicitParams({
            @ApiImplicitParam(name="location",value="结构化地址文本",dataType="String", paramType = "query",example="111.665534,40.858344",required=true)})
    public APIEntity getCity(@RequestAttribute("JwtUserId") Integer id,String location){
        if (StringUtils.isBlank(location)){
            return APIEntity.fail("参数错误：[location=null]");
        }
        AddressVo addressVo=MapUtils.getAddressReGeo(location);
        //客户端上传经纬度则优先解析经纬度
        return APIEntity.success(addressVo);
    }
    /**
     * 客户根据关键字查询地址
     * @param id
     * @param address
     * @return
     */
    @ApiOperation("客户根据关键字查询地址")
    @PostMapping("/get/address/keywords")
    @ApiImplicitParams({
            @ApiImplicitParam(name="address",value="结构化地址文本",dataType="String", paramType = "query",example="内蒙古自治区呼和浩特市新城区成吉思汗大街29号",required=true)})
    public APIEntity addressKeywords(@RequestAttribute("JwtUserId") Integer id,String address){
        if (StringUtils.isBlank(address)){
            return APIEntity.fail("参数错误：[location=null]");
        }
        AddressVo addressVo=MapUtils.getAddressGeo(address);
        //客户端上传经纬度则优先解析经纬度
        return APIEntity.success(addressVo);
    }

    @ApiOperation("城市搜索")
    @GetMapping("/address/get/city")
    @ApiImplicitParams({
            @ApiImplicitParam(name="city",value="城市名称",dataType="String", paramType = "query",example="呼和浩特市"),
            @ApiImplicitParam(name="location",value="经纬度",dataType="String", paramType = "query",example="111.665534,40.858344")})
    public APIEntity getCity(String city,String location) {
        AddressVo add=null;
        if(StringUtils.isNotBlank(city)){
            add = MapUtils.getAddressGeo(city);
        }
        if(StringUtils.isNotBlank(location)){
            add=MapUtils.getAddressReGeo(location);
        }
        if(!add.getCity().contains(city)){
            return APIEntity.fail("城市名不正确！");
        }
        log.info("根据关键字解析地址：{}",add.getAdcode());
        if(add != null){
            return APIEntity.success(add);
        }
        return APIEntity.success(add);
    }


    @ApiOperation("地址搜索")
    @GetMapping("/address/search")
    @ApiImplicitParams({
            @ApiImplicitParam(name="key",value="结构化地址文本",dataType="String", paramType = "query",example="呼和浩特市同城急送",required=true),
            @ApiImplicitParam(name="location",value="经纬度",dataType="String", paramType = "query",example="111.665534,40.858344",required=true)})
    public APIEntity search(String key,String location) {
        log.info("地址搜索的经纬度：{}",location);
        String cityCode;
        if(StringUtils.isNotBlank(location)){
            JSONObject jsonObject = MapUtils.getReGeo(location);
            log.error("###################################:{}",jsonObject.getString("citycode"));
            cityCode = jsonObject.getString("citycode");
        }else {
            AddressVo add=MapUtils.getAddressGeo(key);
            cityCode = add.getAdcode();
        }
        log.info("根据关键字解析地址：{}",cityCode);
       /* if(add != null){
            return APIEntity.success(MapUtils.searchPio(key,cityCode));
        }*/
        return APIEntity.success(MapUtils.searchPio(key,cityCode));
    }
}
