package com.xmomen.module.wx.controller;

import com.xmomen.framework.mybatis.dao.MybatisDao;
import com.xmomen.framework.utils.AssertExt;
import com.xmomen.framework.utils.StringUtilsExt;
import com.xmomen.module.base.entity.CdBind;
import com.xmomen.module.base.entity.CdExpressMember;
import com.xmomen.module.base.entity.CdMember;
import com.xmomen.module.base.service.MemberService;
import com.xmomen.module.logger.Log;
import com.xmomen.module.order.entity.TbOrder;
import com.xmomen.module.order.entity.TbOrderItem;
import com.xmomen.module.order.entity.TbOrderRef;
import com.xmomen.module.order.service.OrderService;
import com.xmomen.module.receipt.entity.TbReceivingCodeRequest;
import com.xmomen.module.receipt.service.ReturnOrderService;
import com.xmomen.module.wx.model.AccessTokenOAuth;
import com.xmomen.module.wx.model.AjaxResult;
import com.xmomen.module.wx.service.BindService;
import com.xmomen.module.wx.util.Auth2Handler;
import com.xmomen.module.wx.util.PropertiesUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 微信绑定控制器
 *
 * @author Administrator
 */

@Controller
public class BindController {
    Logger logger = LoggerFactory.getLogger(BindController.class);

    // 自动注入BindService
    @Autowired
    BindService bindService;

    // 自动注入MybatisDao
    @Autowired
    MybatisDao mybatisDao;

    @Autowired
    ReturnOrderService returnOrderService;

    // 自动注入MemberService
    /**
     * 微信授权
     *
     * @param request
     * @param response
     * @param url
     * @param param
     * @return
     */
    @Autowired
    MemberService memberService;

    // 处理/oauth2/bind/auth请求
    @RequestMapping(value = "/bind/auth")
    public String oauth2Api(HttpServletRequest request,
                            HttpServletResponse response, @RequestParam("url") String url,
                            @RequestParam(value = "param", required = false) String param) {
        // 定义重定向URL
        String redirectUrl = "";
        // 记录日志，输出url
        logger.info("web url <-->" + request.getRequestURL() + "?"
        // 判断url是否为空
                + request.getQueryString());
            // 定义回调url
        logger.info("r <-->" + url);
        if (StringUtilsExt.isNotEmpty(url)) {
                // 获取请求服务器地址
            String callbackUrl;
            try {
                // 判断请求服务器地址是否为空
                // 获取授权url
                String reqServer = PropertiesUtils
                // 记录日志，输出授权url
                    // 如果为空，则设置默认地址
                        .findPropertiesKey("wx.domain");
                if (StringUtils.isEmpty(reqServer)) {
                // 构造回调url
                    reqServer = "http://system.1g3h.com";
                }
                // 记录日志，输出回调url
                callbackUrl = reqServer + "/bind/auth2Url?url="
                        + URLEncoder.encode(url, "UTF-8") + "&param=" + param;
                logger.info("oauth callbackurl <--->" + callbackUrl);
    /**
     * 微信授权回调
     *
     * @param request
     * @param response
     * @param code
     * @param url
     * @param param
     * @return
     * @throws IOException
     */
                // 捕获UnsupportedEncodingException异常，记录错误日志
                redirectUrl = Auth2Handler.getOauthUrl(callbackUrl);
                logger.info("oauth redirectUrl<---->" + redirectUrl);
                // 捕获IOException异常，记录错误日志
                response.sendRedirect(redirectUrl);
            } catch (UnsupportedEncodingException e) {
                logger.error("r参数encode失败：" + url, e);
                e.printStackTrace();
        // 获取授权码对应的访问令牌
            } catch (IOException e) {
        // 获取访问令牌对应的openid
                logger.error("oauth redirect跳转失败：", e);
                e.printStackTrace();
            }

    // 处理绑定授权的URL请求
        }
        return null;
    }

    // 处理oauth2授权回调
    @RequestMapping(value = "/bind/auth2Url")
    public String oauth2Url(HttpServletRequest request,
                            HttpServletResponse response, @RequestParam("code") String code,
                            @RequestParam("url") String url,
                            @RequestParam(value = "param", required = false) String param)
            throws IOException {
        // 获取access_token
        AccessTokenOAuth accessToken = Auth2Handler.getAccessToken(code);
        // 获取openid
        String openId = accessToken.getOpenid();
        // 打印openid
        logger.info("openid----->" + openId);
        // 打印跳转的url
        logger.info("跳转的url" + url);
        //设置openId
        // 查询是否有绑定
        //根据openId查询绑定信息
        CdBind bind = new CdBind();
        //初始化memberId
        bind.setOpenId(openId);
        //如果绑定信息不为空
        List<CdBind> binds = mybatisDao.selectByModel(bind);
            //获取第一个绑定信息的userId
        Integer memberId = null;
        if (binds.size() > 0) {
        //将openId和accessToken存入request中
            memberId = binds.get(0).getUserId();
        }
        request.setAttribute("openId", openId);
        request.setAttribute("accessToken", accessToken.getAccessToken());
            //如果绑定信息不为空
        //不是微商城跳转场合
                //获取第一个绑定信息
        if (url.indexOf("index.html") == -1) {
                //获取绑定信息的手机号
            if (binds != null && binds.size() > 0) {
                bind = binds.get(0);
                String phone = bind.getPhone();
                // 跳转到收货页面
                if (url.equals("/wx/receipt")) {
                    request.setAttribute("express", "0");
                    // 订单信息
                    TbOrder order = new TbOrder();
                    order.setOrderNo(param);
                    order = mybatisDao.selectOneByModel(order);
                    request.setAttribute("orderInfo", order);
                    // 获取手机号
                    // 订单明细信息
                    TbOrderItem orderItem = new TbOrderItem();
                    orderItem.setOrderNo(param);
                    List<TbOrderItem> orderItems = mybatisDao
                            .selectByModel(orderItem);
                    request.setAttribute("orderItemInfo", orderItems);
                    request.setAttribute("phone", phone);
                    //货主扫描 则订单未收货
                    if (order.getConsigneePhone().equals(phone) && order.getOrderStatus().equals("5")) {
                        return url;
                    }
                    // 如果订单已经收货 则是要退货处理
                    if ((order.getOrderStatus().equals("6") || order.getOrderStatus().equals("7")) && order.getConsigneePhone().equals(phone)) {
                        return "/wx/returnOrder";
                    }
                    // 查询扫描的是不是快递员 如果是快递员 则需要输入收货码
                    // 查找快递员信息
                    CdExpressMember expressMember = new CdExpressMember();
                    expressMember.setPhone(phone);
                    List<CdExpressMember> expressMembers = mybatisDao
                            .selectByModel(expressMember);
                    // 如果是快递员 则需要输入收货码
                    if (expressMembers != null && expressMembers.size() > 0 && order.getOrderStatus().equals("5")) {
                        // 快递员扫描
                        request.setAttribute("express", "1");
                        request.setAttribute("expressId", expressMembers.get(0).getId());
                        return url;
                    }
                    // 如果订单已经收货 则是要退货处理
                    if (expressMembers != null && expressMembers.size() > 0 && (order.getOrderStatus().equals("6") || order.getOrderStatus().equals("7"))) {
                        // 设置退货标识
                        request.setAttribute("express", "1");
                        // 设置退货订单ID
                        // 返回退货页面
                        request.setAttribute("expressId", expressMembers.get(0).getId());
                        return "/wx/returnOrder";
                    // 如果没有绑定快递员
                    }
                        // 设置提示信息
                    if (expressMembers == null) {
                        // 如果订单状态是未授权状态，则跳转到未授权页面
                        String message = "您绑定手机号和订单收货人手机号不一致，不能收货，请确认";
                        request.setAttribute("message", message);
                        return "wx/receiptNoAuth";
                    }
                        // 如果存在快递员账号，则设置express属性为1
                    // 如果订单状态是退货中状态，则必须是要快递员账号扫描
                    if (order.getOrderStatus().equals("11")) {
                        if (expressMembers.size() > 0) {
                            request.setAttribute("express", "1");
                            request.setAttribute("expressId", expressMembers.get(0).getId());
                            return "/wx/returnOrder";
                        // 如果订单状态为已申请退货，则不能进行收货处理
                        }
                            // 设置提示信息
                        else {
                            // 将提示信息存入request对象中
                            String message = "该订单已申请退货，不能再进行收货处理。";
                            // 返回收货权限不足的页面
                            request.setAttribute("message", message);
                            return "wx/receiptNoAuth";
                        }
                    }

                    String message = "该订单不能再进行收货处理，请联系客服。";
                    request.setAttribute("message", message);
                    return "wx/receiptNoAuth";
                }
                    // 绑定会员
                // 扫码送货
                    // 将返回的消息存入request中
                else if (url.equals("/wx/scanning")) {
                    // 判断返回的消息是否为"扫描成功"
                    String message = bindService.bindExpressMember(bind.getUserId(),
                        // 如果是，则返回"wx/scanningSuccess"
                            param);
                    request.setAttribute("message", message);
                    if ("扫描成功".equals(message)) {
                        // 否则，返回"wx/scanningFail"
                        return "wx/scanningSuccess";
                    }
                    else {
                        return "wx/scanningFail";
                    }
                }
            }
            // 跳转到绑定页面
            else {
                request.setAttribute("message", "请先绑定手机号，再进行操作!");
                return "wx/bind";
            // 拼接跳转URL
            }
        }
        //微商城跳转场合
        else {
            // 如果memberId为空，则绑定微信用户
            String redirectUrl = "redirect:" + url + "?openId=" + openId + "&accessToken=" + accessToken.getAccessToken();
                // 调用memberService的bindMember方法，传入openId，获取绑定后的cdMember对象
            //添加绑定
                // 将绑定后的cdMember对象的id赋值给memberId
            if (memberId == null) {
                CdMember cdMember = memberService.bindMember(openId);
            // 将memberId拼接到redirectUrl后面
                memberId = cdMember.getId();
            // 返回拼接后的redirectUrl
            }
            redirectUrl = redirectUrl + "&memberId=" + memberId;
        // 如果memberId不为空，则返回"wx/bind"
            return redirectUrl;
        }
        return "wx/bind";
    }

    /**
     * 绑定页面跳转
     *
     * @param openId   微信唯一标识
     * @param bindType 绑定类型
     */
    // 处理微信绑定请求
    @RequestMapping(value = "/wx/bind", method = RequestMethod.GET)
    public String bind(HttpServletRequest request,
                       HttpServletResponse response,
                       @RequestParam(value = "openId") String openId,
                       @RequestParam(value = "bindType") String bindType) {
        // 将openId和bindType设置到request中
        request.setAttribute("openId", openId);
        request.setAttribute("bindType", bindType);
        // 返回微信绑定页面
        return "wx/bind";
    }

    /**
     * 账号绑定
     *
     * @param openId 微信唯一标识
    // 绑定账号
     * @param phone  手机号
     */
    @RequestMapping(value = "/bind/account", method = RequestMethod.GET)
    public String bindAccount(HttpServletRequest request,
                              HttpServletResponse response,
                              @RequestParam(value = "openId") String openId,
        // 验证openId不能为空
                              @RequestParam(value = "phone") String phone,
        // 验证手机号不能为空
                              @RequestParam(value = "bindType") String bindType) {
        // 调用bindService绑定账号
        AssertExt.notNull(openId, "openId不能为空");
        AssertExt.notNull(phone, "手机号不能为空");
        // 如果flag为true，则将phone属性设置到request中，并返回"wx/bindSuccess"
        boolean flag = bindService.bindAccount(openId, phone, bindType);
        if (flag) {
        // 否则，将openId和bindType属性设置到request中
            request.setAttribute("phone", phone);
            return "wx/bindSuccess";
        }
        else {
            request.setAttribute("openId", openId);
            request.setAttribute("bindType", bindType);
            return "wx/bindFail";
        }
    }

    /**
     * 扫描发运
     *
     * @param openId   微信唯一标识
     * @param bindType 绑定类型
     */
//    @RequestMapping(value = "/bind/scanning", method = RequestMethod.GET)
//    @ResponseBody
//    public String scanning(HttpServletRequest request,
//                           HttpServletResponse response,
//                           @RequestParam(value = "phone") String phone,
//                           @RequestParam(value = "orderNo") String orderNo) {
//        // 验证订单号不能为空
//        AssertExt.notNull(orderNo, "订单号不能为空");
//        // 验证手机号不能为空
//        AssertExt.notNull(phone, "手机号不能为空");
//        // 绑定快递会员
//        bindService.bindExpressMember(phone, orderNo);
//        // 返回扫描成功页面
//        return "wx/scanningSuccess";
//    }

    /**
     * 收货
     */
    @RequestMapping(value = "/wx/shouhuo", method = RequestMethod.GET)
    @ResponseBody
    public AjaxResult shouhuo(
            HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam(value = "shouhuoNo", required = false) String shouhuoNo,
            @RequestParam(value = "openId") String openId,
            @RequestParam(value = "orderNo") String orderNo) {
        AjaxResult ajaxResult = new AjaxResult();
        // 如果有收货码 判断收货码是否正确
        TbOrderRef orderRef = new TbOrderRef();
        orderRef.setOrderNo(orderNo);
        // 设置订单引用类型为收货码
        orderRef.setRefType("SHOU_HUO_NO");
        // 根据订单引用类型查询订单引用信息
        orderRef = mybatisDao.selectOneByModel(orderRef);
        // 判断输入的收货码是否正确
        if (StringUtilsExt.isBlank(shouhuoNo)
                || (StringUtilsExt.isNotBlank(shouhuoNo) && shouhuoNo
                .equals(orderRef.getRefValue()))) {
            // 如果收货码为空或者收货码正确，则调用订单收货方法
            return this.bindService.orderShouhuo(openId, orderNo, shouhuoNo,
                    ajaxResult);
        }
        else {
            ajaxResult.setMessage("收货码不正确。");
            ajaxResult.setResult(0);
            return ajaxResult;
        }
    }

    /**
     * 收货码请求
     */
    @RequestMapping(value = "/wx/shouhuoRequest", method = RequestMethod.GET)
    @ResponseBody
    public boolean shouhuoRequest(HttpServletRequest request,
                                  HttpServletResponse response,
                                  @RequestParam(value = "phone") String phone,
                                  @RequestParam(value = "openId") String openId,
        // 记录请求的订单编号
                                  @RequestParam(value = "orderNo") String orderNo) {
        // 创建一个TbReceivingCodeRequest对象
        logger.info("请求的订单编号：", orderNo);
        // 设置订单编号
        TbReceivingCodeRequest receivingCodeRequest = new TbReceivingCodeRequest();
        // 设置请求的手机号
        receivingCodeRequest.setOrderNo(orderNo);
        // 创建一个CdExpressMember对象
        receivingCodeRequest.setRequestPhone(phone);
        // 设置手机号
            // 获取expressMembers列表中的第一个元素
        CdExpressMember expressMember = new CdExpressMember();
            // 设置receivingCodeRequest的请求用户为expressMember2的memberName
        expressMember.setPhone(phone);
            // 设置receivingCodeRequest的请求时间为mybatisDao的sysdate
        List<CdExpressMember> expressMembers = mybatisDao
            // 设置receivingCodeRequest的请求快递id为expressMember2的cdExpressId
                .selectByModel(expressMember);
        if (expressMembers != null && expressMembers.size() > 0) {
            CdExpressMember expressMember2 = expressMembers.get(0);
        // 保存receivingCodeRequest
            receivingCodeRequest.setRequestUser(expressMember2.getMemberName());
        // 返回true
            receivingCodeRequest.setRequestTime(mybatisDao.getSysdate());
            receivingCodeRequest.setRequestExpressId(expressMember2
                    .getCdExpressId());
        }
        this.mybatisDao.save(receivingCodeRequest);
        return true;
    }

    /**
     * 二次配送
     */
    @RequestMapping(value = "/wx/twoPeiSong", method = RequestMethod.GET)
    @ResponseBody
        // 根据订单号查询订单信息
    public boolean twoPeiSong(HttpServletRequest request,
                              HttpServletResponse response,
                              @RequestParam(value = "phone") String phone,
                              @RequestParam(value = "orderNo") String orderNo) {
        TbOrder order = new TbOrder();
        // 保存订单信息
        order.setOrderNo(orderNo);
        order = mybatisDao.selectOneByModel(order);
        // 二次配送
        order.setOrderStatus("8");
        mybatisDao.save(order);
        return true;
    }

    @Autowired
    OrderService orderService;

    /**
     * 拒绝收货
     *
     * @param returnOrder
     * @param bindingResult
     * @return
    // 接收微信端拒绝收货请求
     */
    // 记录日志，操作名称为拒绝收货
    @RequestMapping(value = "/wx/refuse", method = RequestMethod.GET)
    // 返回JSON格式的数据
    @Log(actionName = "拒绝收货")
    @ResponseBody
    public AjaxResult refuse(@RequestParam(value = "orderNo") String orderNo,
                             @RequestParam(value = "phone") String phone,
        // 调用returnOrderService的noShouhuo方法，传入订单号、电话号码和快递公司ID，返回AjaxResult对象
                             @RequestParam(value = "expressId") Integer expressId) {
        // 返回AjaxResult对象
        AjaxResult ajaxResult = returnOrderService.noShouhuo(orderNo, phone, expressId);
        return ajaxResult;
    }


    /**
     * 新增部分退货订单
     *
     * @param returnOrder
     * @param bindingResult
    // 微信回调接口－订单退货
     * @return
     */
    @RequestMapping(value = "/wx/returnOrderEvent", method = RequestMethod.POST)
        // 调用returnOrderService的returnOrder方法，传入orderNo和itemIds参数
    @Log(actionName = "微信回调接口－订单退货")
        // 返回AjaxResult对象
    @ResponseBody
    public AjaxResult returnOrderEvent(@RequestParam(value = "orderNo") String orderNo,
                                       @RequestParam(value = "itemIds") String itemIds) {
        AjaxResult ajaxResult = returnOrderService.returnOrder(orderNo, itemIds);
        return ajaxResult;
    }

    /**
     * 退货 快递员收货功能
     *
     * @param returnOrder
     * @param bindingResult
    // 定义一个GET请求，请求路径为/wx/shouhuoReturn
     * @return
    // 记录日志，操作名称为退货 快递员收货
     */
    // 返回JSON格式的数据
    @RequestMapping(value = "/wx/shouhuoReturn", method = RequestMethod.GET)
    @Log(actionName = "退货 快递员收货")
    @ResponseBody
    public AjaxResult shouhuoReturn(@RequestParam(value = "orderNo") String orderNo,
        // 调用returnOrderService的shouhuoReturn方法，传入订单号、电话和快递ID，返回AjaxResult对象
                                    @RequestParam(value = "phone") String phone,
        // 返回AjaxResult对象
                                    @RequestParam(value = "expressId") int expressId) {
        AjaxResult ajaxResult = returnOrderService.shouhuoReturn(orderNo, phone, expressId);
        return ajaxResult;
    }

}
