package com.yunniu.farming.webadmin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yunniu.farming.result.Result;
import com.yunniu.farming.util.DateTools;
import com.yunniu.farming.util.DateUtils;
import com.yunniu.farming.util.StringHelper;
import com.yunniu.farming.util.WxPayAppUtils;
import com.yunniu.farming.webadmin.dao.*;
import com.yunniu.farming.webadmin.model.*;
import com.yunniu.farming.webadmin.service.GroupOrderService;
import com.yunniu.farming.webadmin.service.WxService;
import com.yunniu.farming.wx.WxConfigUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class OrderMainServiceImpl {


    @Autowired
    private OrderMainDao orderMainDao;

    @Autowired
    private OrderSubDao orderSubDao;

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private IntegralrecDao integralrecDao;

    @Autowired
    private GroupOrderService orderService;
    @Autowired
    private OrderRefundMapper refundMapper;

    @Autowired
    @Lazy
    private WxService wxService;


    /**
     * 分页查询所有数据
     *
     * @return
     */
    public List<OrderMain> selectByParamPageList(OrderMain doc) {
        return this.orderMainDao.selectByParamPageList(doc);
    }


    /**
     * FRICE TODO 带参 常规查询
     */
    public List<OrderMain> findByParam(OrderMain doc) {
        return this.orderMainDao.selectByParam(doc);
    }

    /**
     * 根据id删除用户
     */
    public Result deleteByid(int id) {
        int i = this.orderMainDao.deleteById(id);
        if (i > 0) {
            return Result.success("删除成功");
        }
        return Result.error();
    }

    /**
     * 按照订单主表ID查找全部数据
     */
    public OrderMain findByid(Integer id) {
        OrderMain u = this.orderMainDao.selectByPrimaryKey(id);
        return u;
    }


    /**
     * 创建订单
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderMain addOrder(OrderMain item) {

        if (item.getId() == null) {

            if (item.getItype() != null && item.getItype().equals(OrderMain.ITYPE_GROUP)) {
                GroupOrder order = orderService.addGroupOrder(item);
                item.setGroupOrderId(order.getId());
            }
            // 单据日期
            item.setSorderdate(DateTools.getDate("yyyy-MM-dd"));
            // 提交订单时间
            item.setTordertime(DateUtils.getToday().getTime());
            // 单据编号： 当前系统时间+随机4位数
            item.setSorderno(StringHelper.getOrderno());

            // 状态初始化
            if (item.getIpaystatus() == null) {
                item.setIpaystatus(OrderMain.PAY_STATUS_NO);// 未支付
            }

            if (item.getItype() == null) {
                item.setItype(OrderMain.ITYPE_TAKE);//外卖订单
            }
            item.setIstatus(OrderMain.STATUS_NOPAY);//未付款

            item.setIpaytype(10);//微信支付

            // 1.保存主表信息
            int i = this.orderMainDao.insert(item);

            // 2.批量保存订单子表信息
            if (item.getSubs() != null && item.getSubs().size() > 0) {
                for (OrderSub sub : item.getSubs()) {
                    sub.setMainid(item.getId());// 添加 主表id
                }
                // 调用 子表批量保存方法
                this.orderSubDao.insertBatch(item.getSubs());
            }
        }

        return item;
    }


    /**
     * 创建订单
     *
     * @return
     */
    public Result addIntOrder(OrderMain item) {

        if (item.getDactscore() == null || item.getDactscore() <= 0) {
            return Result.error("创建订单失败");
        }

        if (item.getItype() != null && item.getItype().equals(OrderMain.ITYPE_GROUP)) {
            GroupOrder order = orderService.addGroupOrder(item);
            item.setGroupOrderId(order.getId());
        }
        // 单据日期
        item.setSorderdate(DateTools.getDate("yyyy-MM-dd"));
        // 提交订单时间
        item.setTordertime(DateUtils.getToday().getTime());
        // 单据编号： 当前系统时间+随机4位数
        item.setSorderno(StringHelper.getOrderno());

        // 状态初始化
        if (item.getIpaystatus() == null) {
            item.setIpaystatus(OrderMain.PAY_STATUS_NO);// 未支付
        }
        if (item.getItype() == null) {
            item.setItype(OrderMain.ITYPE_TAKE);//外卖订单
        }
        item.setIstatus(OrderMain.STATUS_NOPAY);//未付款

        item.setIpaytype(30);//积分支付

        // 1.保存主表信息
        int i = this.orderMainDao.insert(item);

        // 2.批量保存订单子表信息
        if (item.getSubs() != null && item.getSubs().size() > 0) {
            for (OrderSub sub : item.getSubs()) {
                sub.setMainid(item.getId());// 添加 主表id
            }
            // 调用 子表批量保存方法
            this.orderSubDao.insertBatch(item.getSubs());
        }

        return Result.success(item);
    }


    /**
     * @编辑
     */
    public Result update(OrderMain doc) {

        if (doc.getId() == null) return Result.error();

        OrderMain orderMain = this.orderMainDao.selectById(doc.getId());

        if (orderMain == null) {
            return Result.error("订单信息不存在");
        }

        //判断用户积分是否足够
        if (doc.getDactscore() != null) {

            // 查询该用户的积分
            Integralrec integralrec = new Integralrec();
            integralrec.setCustomerid(orderMain.getCustomerid());
            Double aDouble = this.integralrecDao.sumIntegral(integralrec);

            if (aDouble == null || aDouble < 0) return Result.error("用户积分不足");

            // 用户收入积分减去支付积分要大于订单积分价格
            // 用户余额要大于支付额
            if ((aDouble != null ? aDouble : 0) < doc.getDactscore()) {
                return Result.error("积分不足");
            }

        }

        int i = this.orderMainDao.updateById(doc);

        if (i > 0) {
            return Result.success("修改成功");
        }

        return Result.error();

    }


    //根据多参数查询订单数量
    public int findOrderNum(OrderMain orderMain) {
        return orderMainDao.countOrderNum(orderMain);
    }

    //根据多参数查询订单金额
    public Double findOrderMoney(OrderMain orderMain) {
        return orderMainDao.countOrderMoney(orderMain);
    }

    //更改订单服务中
    public Result updateFwStatus(OrderMain order) {

        if (order.getId() == null) {
            return Result.error();
        }

        //待收货
        order.setIstatus(OrderMain.STATUS_WAITING);
        // 发货备注
        order.setSdef5(order.getRemark());
        this.orderMainDao.updateById(order);

        return Result.success();

    }


    //更改订单已完成
    public Result updateOkStatus(OrderMain order) {

        if (order.getId() == null) {
            return Result.error();
        }

        //已完成
        order.setIstatus(OrderMain.STATUS_COMPLETE);

        //完成时间
        order.setTovertime(new Date());

        this.orderMainDao.updateById(order);

        return Result.success("成功");

    }


    /**
     * 更改订单退款申请通过
     */
    @Transactional(rollbackFor = Exception.class)
    public Result refundApplicationPass(OrderMain order) {
        if (order.getId() == null) {
            return Result.error();
        }
//        OrderMain orderMain = this.orderMainDao.selectById(order.getId());
        OrderRefund orderRefund = refundMapper.selectOne(Wrappers.<OrderRefund>lambdaQuery()
                .eq(OrderRefund::getOrderMianId, order.getId())
                .eq(OrderRefund::getRefundStatus, 1));
        if (orderRefund.getRefundType().equals("1")) {
            this.refundReceive(order, 1);
        } else {
            orderRefund.setRefundStatus("4");
            refundMapper.updateById(orderRefund);
            List<OrderSub> orderSubs = this.orderSubDao.selectList(Wrappers.<OrderSub>lambdaQuery().eq(OrderSub::getMainid, order.getId()).eq(OrderSub::getSdef1, 1));
            orderSubs.forEach(sub -> {
                sub.setSdef1("2");
                orderSubDao.updateById(sub);
            });
        }
        return Result.success("成功");
    }

    /**
     * 更改订单退款申请拒绝
     */
    @Transactional(rollbackFor = Exception.class)
    public Result refundApplicationRefuse(OrderMain order) {
        if (order.getId() == null) {
            return Result.error();
        }
        order.setIrefundstatus(OrderMain.STATUS_REFUND_REFUSE);
        this.orderMainDao.updateById(order);
        OrderRefund orderRefund = refundMapper.selectOne(Wrappers.<OrderRefund>lambdaQuery()
                .eq(OrderRefund::getOrderMianId, order.getId())
                .eq(OrderRefund::getRefundStatus, 1));
        orderRefund.setRefundStatus("3");
        refundMapper.updateById(orderRefund);
        List<OrderSub> orderSubs = this.orderSubDao.selectList(Wrappers.<OrderSub>lambdaQuery().eq(OrderSub::getMainid, order.getId()).eq(OrderSub::getSdef1, 1));
        orderSubs.forEach(sub -> {
            sub.setSdef1("3");
            sub.setSdef3("0");
            orderSubDao.updateById(sub);
        });
        return Result.success("成功");
    }

    /**
     * 已收到退回货物，开始退款
     *
     * @param order
     * @param type 1仅退款， 4 退货退款
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result refundReceive(OrderMain order, Integer type) {
        // 根据id获取订单信息
        OrderMain orderMain = this.orderMainDao.selectById(order.getId());
        OrderRefund orderRefund = refundMapper.selectOne(Wrappers.<OrderRefund>lambdaQuery()
                .eq(OrderRefund::getOrderMianId, order.getId())
                .eq(OrderRefund::getRefundStatus, type));
        orderRefund.setRefundStatus("6");
        refundMapper.updateById(orderRefund);
        this.orderMainDao.updateById(orderMain);
        log.info("收货成功，开始退款：{}", JSON.toJSONString(orderMain));
        try {
            wxService.wxRefund(orderMain.getCustomerid(), orderMain.getId(), "用户申请退款", null);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return Result.success("成功");
    }

    @Transactional(rollbackFor = Exception.class)
    public Result cancelOrder(OrderMain order) {

        if (order.getId() == null) {
            return Result.error();
        }

        OrderMain orderMain = this.orderMainDao.selectById(order.getId());

        //已支付订单 无法取消
        if (orderMain.getIpaystatus().equals(OrderMain.PAY_STATUS_OK)) {
            try {
                wxService.wxRefund(orderMain.getCustomerid(), orderMain.getId(), "用户申请退款", null);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        //已取消
        order.setIstatus(OrderMain.STATUS_CANCEL);

        this.orderMainDao.updateById(order);

        return Result.success("成功");

    }


    //app支付
    public Result appWxPay(Integer userId, Integer orderId, HttpServletRequest request) throws Exception {
        OrderMain order = orderMainDao.selectByPrimaryKey(orderId);
        if (order == null || !order.getCustomerid().equals(userId)) {
            return new Result(102);
        }
        //商品名称封装
        String prodNames = "Q&A." + order.getSorderno();

        DecimalFormat decimalFormat = new DecimalFormat("###################");

        // 3. 微信官方 预支付方法，此为前端调起微信支付的参数
        Map<String, Object> wxPayData = WxPayAppUtils.wxPay(
                request,
                WxConfigUtil.APPID,
                WxConfigUtil.MCH_ID,
                WxConfigUtil.API_KEY,
                WxConfigUtil.notify_url,
                prodNames,
                order.getSorderno(),
                decimalFormat.format(order.getDactmoney() * 100),
                order.getId().toString()
        );

        //将订单信息也返回页面
        Map<String, Object> mr = new HashMap<String, Object>();
        mr.put("order_id", order.getId());
        mr.put("result_code", wxPayData.get("result_code"));

        //将状态码属性移除
        wxPayData.remove("result_code");

        mr.put("wxpaydata", wxPayData);

        return Result.success(mr);

    }


    //商品 订单逻辑处理
    protected void handleCommProuctOrder(OrderMain co) {

        if (co == null) return;

        // 支付回调标志，防止 多次回调
        if (StringUtils.isEmpty(co.getSdef4())) {

            //支会回调标志
            co.setIstatus(OrderMain.STATUS_YESPAY);//待发货
            co.setIpaystatus(OrderMain.PAY_STATUS_OK);//支付成功
            co.setTpaytime(new Date());//支付时间
            co.setSdef4("1");

            this.update(co);

            //判断是否 有抵扣的积分
            if (co.getDactscore() != null && co.getDactscore() > 0) {
                //扣除用户抵扣所用的积分
                Integralrec integralrec = new Integralrec();
                integralrec.setDexpend(co.getDactscore());
                integralrec.setOrderid(co.getId());
                integralrec.setCustomerid(co.getCustomerid());
                integralrec.setItype(Integralrec.INTEGRALREC_ORDOUT);//下单抵扣
                integralrec.setSdesc("下单抵扣");
                integralrec.setSoprdate(DateTools.getDate("yyyy-MM-dd"));
                integralrec.setToprtime(new Date());
                integralrecDao.insertSelective(integralrec);
            }


            //奖励用户下单返利积分 1元= 10积分
            if (co.getDactmoney() != null && co.getDactmoney() > 0) {

                //保留整数位
                double floor = Math.floor(co.getDactmoney());
                double dincome = floor * 10;

                if (dincome > 0) {
                    //增加积分收入记录
                    Integralrec inte = new Integralrec();
                    inte.setDincome(dincome);
                    inte.setOrderid(co.getId());
                    inte.setCustomerid(co.getCustomerid());
                    inte.setItype(Integralrec.INTEGRALREC_NEWORD);//下单返利
                    inte.setSdesc("下单返利");
                    inte.setSoprdate(DateTools.getDate("yyyy-MM-dd"));
                    inte.setToprtime(new Date());
                    integralrecDao.insertSelective(inte);
                }


            }


        }
    }

    //积分支付
    public Result integralPay(Integer userId, Integer orderId) {

        OrderMain ord = orderMainDao.selectByPrimaryKey(orderId);
        if (ord == null || !ord.getCustomerid().equals(userId)) {
            return Result.error("订单参数错误");
        }

        //积分金额
        if (ord.getDactscore() == null) {
            return Result.error("订单参数错误");
        }

        //支付状态
        if (!ord.getIpaystatus().equals(OrderMain.PAY_STATUS_NO)) {
            return Result.error("订单参数错误");
        }

        //订单状态
        if (!ord.getIstatus().equals(OrderMain.STATUS_NOPAY)) {
            return Result.error("订单参数错误");
        }

        //判断用户积分是否足够
        // 查询该用户的积分
        Integralrec inte = new Integralrec();
        inte.setCustomerid(ord.getCustomerid());
        Double inteNum = this.integralrecDao.sumIntegral(inte);

        if (inteNum == null || inteNum < 0) return Result.error("积分不足,无法支付");

        // 用户收入积分减去支付积分要大于订单积分价格
        if ((inteNum != null ? inteNum : 0) < ord.getDactscore()) {
            return Result.error("积分不足,无法支付");
        }

        //扣除用户积分
        Integralrec integralrec = new Integralrec();
        integralrec.setOrderid(orderId);
        integralrec.setItype(Integralrec.INTEGRALREC_DUIPRO);
        integralrec.setDexpend(ord.getDactscore());
        integralrec.setCustomerid(userId);
        integralrec.setSdesc("兑换商品");
        integralrec.setSoprdate(DateTools.getDate("yyyy-MM-dd"));
        integralrec.setToprtime(new Date());
        int res = integralrecDao.insert(integralrec);
        if (res <= 0) {
            return Result.success("支付失败");
        }
        //改变订单状态
        //待发货
        ord.setIstatus(OrderMain.STATUS_YESPAY);
        //已支付
        ord.setIpaystatus(OrderMain.FLAG_Y);
        //支付时间
        ord.setTpaytime(new Date());//支付时间
        this.orderMainDao.updateById(ord);

        return Result.success("支付成功");
    }

    /**
     * 获取用户最后一次填写的地址信息
     *
     * @param userId 用户id
     * @return
     */
    public Result getLastOrderAddres(Integer userId) {

        return Result.success(this.orderMainDao.getLastOrderAddres(userId));
    }

    /**
     * 申请退款
     *
     * @param order
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Result refundOrder(OrderMain order, JSONArray ids) {
        OrderMain orderMain = this.orderMainDao.selectById(order.getId());
//        orderMain.setSrefundreason(order.getSrefundreason());
//        orderMain.setSrefundpic(order.getSrefundpic());
//        orderMain.setIrefundstatus(order.getIrefundstatus());
        OrderRefund orderRefund = new OrderRefund();
        Double refundmoney = Double.valueOf(0.0);
        if (CollectionUtils.isNotEmpty(ids)) {
            List<JSONObject> objects = JSON.parseArray(ids.toJSONString(), JSONObject.class);
            List<OrderSub> orderSubs = this.orderSubDao.selectList(Wrappers.<OrderSub>lambdaQuery().eq(OrderSub::getMainid, order.getId()));
            for (JSONObject id : objects) {
                int num = (int) id.get("num");
                if (num == 0) {
                    throw new RuntimeException("退款数量不可以为0");
                }
                OrderSub sub = orderSubs.stream().filter(orderSub -> orderSub.getId().equals(id.get("id")) ).findAny().get();
                if (ObjectUtils.isNotEmpty(sub)) {
                    if ((sub.getIpronum() - (sub.getSdef3() != null ? Integer.parseInt(sub.getSdef3()) : 0)) < num) {
                        return Result.error("退款数量不能大于购买数量");
                    }
                    if (sub.getIpronum() > num) {
                        orderRefund.setPortion("0");
                    } else {
                        orderRefund.setPortion("1");
                    }
                    sub.setSdef1("1");
                    sub.setSdef3(((sub.getSdef3() != null ? Integer.parseInt(sub.getSdef3()) : 0) + num) + "");
                    refundmoney = refundmoney + (sub.getSgoodprice() * num);
                    this.orderSubDao.updateById(sub);
                }
            }
            if (orderSubs.size() > ids.size()) {
                orderRefund.setPortion("0");
            }
        } else {
            refundmoney = orderMain.getDactmoney();
        }
        orderRefund.setOrderMianId(Long.valueOf(orderMain.getId()));
        orderRefund.setRefundDetail(ids.toJSONString());
        orderRefund.setRefundMoney(refundmoney);
        orderRefund.setRefundReason(order.getSrefundreason());
        orderRefund.setRefundImg(order.getSrefundpic());
        orderRefund.setRefundTime(new Date());
        orderRefund.setRefundType(order.getIrefundstatus() == 106 ? "1" : "2");
        orderRefund.setRefundStatus("1");
        refundMapper.insert(orderRefund);
//        orderMain.setIrefundmoney(refundmoney);
//        this.orderMainDao.updateById(orderMain);
        return Result.success("成功");
    }

    public List<OrderMain> selectByParamPageRefundGroupList(OrderMain item) {
        return this.orderMainDao.selectByParamPageRefundGroupList(item);
    }

    public Result saveCourierNumber(OrderMain order) {
        OrderMain orderMain = this.orderMainDao.selectById(order.getId());
        orderMain.setIrefundstatus(OrderMain.STATUS_REFUND);
        orderMain.setCouriernumber(order.getCouriernumber());
        this.orderMainDao.updateById(orderMain);
        return Result.success("成功");
    }

    /**
     * 仅退款
     *
     * @param order
     * @return
     */
    public Result refundOnly(OrderMain order) {
        OrderMain orderMain = this.orderMainDao.selectById(order.getId());
        orderMain.setIrefundstatus(OrderMain.STATUS_REFUND_ONLY);
        this.orderMainDao.updateById(orderMain);
        return Result.success("成功");
    }
}
