package com.cftech.order.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cftech.accounts.model.MpAccountsEntity;
import com.cftech.accounts.service.MpAccountsService;
import com.cftech.base.codingrule.utils.CodingruleUtils;
import com.cftech.base.org.api.QyMsgUtil;
import com.cftech.base.org.model.Qyuser;
import com.cftech.base.org.service.QyuserService;
import com.cftech.core.sql.Sort;
import com.cftech.core.util.Constants;
import com.cftech.core.util.DateFormatUtils;
import com.cftech.core.util.StringUtils;
import com.cftech.core.util.SystemConfig;
import com.cftech.invoice.model.Invoice;
import com.cftech.invoice.model.InvoiceDto;
import com.cftech.invoice.service.InvoiceService;
import com.cftech.mp.fans.model.MpFanssEntity;
import com.cftech.mp.fans.service.MpFanssService;
import com.cftech.order.model.*;
import com.cftech.order.dao.OrderMapper;
import com.cftech.order.pay.WechatPayUtils;
import com.cftech.order.service.OrderService;
import com.cftech.core.generic.GenericDao;
import com.cftech.core.generic.GenericServiceImpl;
import com.cftech.core.sql.Conds;

import com.cftech.order.utils.InvoiceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 订单管理ServiceImpl
 *
 * @author Licc
 * @date: 2020-10-10 14:20
 */
@Slf4j
@Service("orderService")
public class OrderServiceImpl extends GenericServiceImpl<Order> implements OrderService {

    @Autowired
    @Qualifier("orderMapper")
    private OrderMapper orderMapper;

    @Autowired
    private MpAccountsService mpAccountsService;

    @Autowired
    private InvoiceUtil invoiceUtil;

    @Autowired
    private InvoiceService invoiceService;

    @Autowired
    private CodingruleUtils codingruleUtils;

    @Autowired
    private MpFanssService mpFanssService;

    @Autowired
    private QyuserService qyuserService;

    @Autowired
    private QyMsgUtil qyMsgUtil;


    @Override
    public GenericDao<Order> getGenericMapper() {
        return orderMapper;
    }

    @Override
    public List<Order> fetchSearchBy(Conds conds, Sort sort, int page, int pageSize, Long userid) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("conds", conds);
        params.put("offset", page > 0 ? page : 0);
        params.put("limit", pageSize > 0 ? pageSize : 0);
        params.put("sort", sort);
        //非管理员查询所有
        if (userid != null && userid != 1L) {
            params.put("userid", userid);
        }
        return orderMapper.fetchSearchByPage(params);
    }

    @Override
    public Integer count(Conds conds, Long userid) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("conds", conds);
        //非管理员查询所有
        if (userid != null && userid != 1L) {
            params.put("userid", userid);
        }
        return orderMapper.count(params);
    }

    @Override
    public List<ProductOrder> listProduct() {
        return orderMapper.listProduct();
    }

    @Override
    public OrderFromVO fetchId(Serializable id) {
        return orderMapper.fetchId(id);
    }

    @Override
    public List<OrderFromVO> fetchProductId(Serializable id) {
        return orderMapper.fetchProductId(id);
    }

    @Override
    public Integer updateStatus(Long id, String status, String orderCancel) {
        Map<String, Object> params = new HashMap<>();
        params.put("id", id);
        params.put("status", status);
        params.put("orderCancel", orderCancel);
        return orderMapper.updateStatus(params);
    }

    @Transactional
    @Override
    public JSONObject newlyAdded(String datas, Long accountsId) {
        JSONObject rtnJson = new JSONObject();
        OrderDetailDto orderDetailDto = null;
        Map<String, Object> params = new HashMap<>();
        datas = datas.replaceAll("&quot;", "\"");
        JSONArray jsonArray = JSONArray.parseArray(datas);

        Long id = null;
        Double orderAmount = null;
        Order order = null;
        boolean flag = false;
        try {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject obj = jsonArray.getJSONObject(i);
                params.put("accountsId", accountsId);
                params.put("id", obj.getLong("id"));
                params.put("idDetail", obj.getString("idDetail"));
                params.put("productId", obj.getLong("productId"));
                params.put("drugsNum", obj.getLong("drugsNum"));
                params.put("price", obj.getDouble("price"));
                params.put("amount", obj.getDouble("amount"));
                params.put("orderAmount", obj.getDouble("orderAmount"));

                //获取产品信息
                ProductDto productDtos = orderMapper.fetchProduct(params);

                if (order == null) {
                    id = obj.getLong("id");
                    orderAmount = obj.getDouble("orderAmount");

                    Conds orderConds = new Conds();
                    orderConds.equal("o.del_flag", Constants.DEL_FLAG_0);
                    orderConds.equal("o.id", id);
                    order = this.fetchSearchByConds(orderConds);
                    if (order != null) {
                        order.setOrderAmount(orderAmount);
                    } else {
                        rtnJson.put("errorNo", "1");
                        return rtnJson;
                    }
                }

                orderDetailDto = new OrderDetailDto();
                orderDetailDto.setOrderId(id);
                orderDetailDto.setOrderCode(order.getNumber());
                orderDetailDto.setOpenid(order.getOpenid());
                orderDetailDto.setPrice(obj.getDouble("price"));
                orderDetailDto.setAmount(obj.getDouble("amount"));
                orderDetailDto.setDrugsId(productDtos.getId());
                orderDetailDto.setDrugsNum(obj.getLong("drugsNum"));
                orderDetailDto.setDrugsCode(productDtos.getProductNumber());
                orderDetailDto.setDrugsSku(productDtos.getFormat());
                orderDetailDto.setAccountsId(accountsId);
                Integer result = orderMapper.saveDetill(orderDetailDto);
                if (result > 0) {
                    flag = true;
                }
            }

            //获取商户号订单内容
            if (flag) {
                JSONObject mchObj = WechatPayUtils.genenatePay(order);
                if (mchObj != null) {
                    order.setStatus("1");
                    order.setOrderTime(new Date());
                    order.setOrderAmount(orderAmount);
                    order.setRemarks(mchObj.toString());
                    boolean bool = this.update(order);
                    if (bool) {
                        rtnJson.put("errorNo", "0");
                        rtnJson.put("errorMsg", "修改成功");
                        return rtnJson;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            rtnJson.put("errorNo", "1");
        }
        rtnJson.put("errorNo", "1");
        return rtnJson;

    }

    @Override
    public JSONObject deleteAll(Long id) {
        JSONObject jsonObject = new JSONObject();
        Integer integer = orderMapper.deleteAll(id);
        if (integer < 0) {
            jsonObject.put("errorNo", "1");
        }
        jsonObject.put("errorNo", "0");
        return jsonObject;
    }

    @Override
    public JSONObject confirm(OrderMobileDto orderMobileDto) {
        MpAccountsEntity mpAccountsAppid = mpAccountsService.getMpAccountsAppid(orderMobileDto.getAppId());
        JSONObject rtnJson = new JSONObject();
        try {
            if (StringUtils.isEmpty(orderMobileDto.getOpenId())) {
                rtnJson.put("errorNo", "1");
                rtnJson.put("errorMsg", "openid不能为空");
                return rtnJson;
            }

            List<OrderMobile> orderMobiles = orderMapper.orderFall(orderMobileDto);
            for (OrderMobile orderMobile : orderMobiles) {
                if (orderMobileDto.getId() != null && orderMobile.getStatus().equals("1")) {
                    Date orderTime = DateFormatUtils.formatDate(orderMobile.getOrderTime(), "yyyy-MM-dd HH:mm:ss");
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(orderTime);
                    calendar.add(Calendar.HOUR, 2);
                    orderTime = calendar.getTime();
                    long time = orderTime.getTime() - new Date().getTime();
                    if (time < 60 * 60 * 2 * 1000) {
                        orderMobile.setTime(time);
                    } else {
                        orderMobile.setTime(0);
                    }
                }

                if (orderMobile.getId() != null) {
                    List<ProductMobile> mobiles = orderMapper.orderDetill(orderMobile.getId());
                    orderMobile.setProductMobile(mobiles);
                }
            }


            JSONObject object = new JSONObject();
            object.put("orderMobiles", orderMobiles);

            rtnJson.put("errorNo", "0");
            rtnJson.put("data", object);
        } catch (Exception e) {
            e.printStackTrace();
            rtnJson.put("errorNo", "1");

        }
        return rtnJson;
    }

    @Override
    public JSONObject orderSize(String openId, String appId) {
        JSONObject rtnJson = new JSONObject();
        try {
            if (StringUtils.isEmpty(openId)) {
                rtnJson.put("errorNo", "0");
                rtnJson.put("errorMsg", "openid不能为空");
                return rtnJson;
            }
            MpAccountsEntity mpAccountsAppid = mpAccountsService.getMpAccountsAppid(appId);
            OrderSizeVO productMobiles = orderMapper.orderSize(openId);
            if (productMobiles != null) {
                rtnJson.put("errorNo", "0");
                rtnJson.put("data", productMobiles);
                return rtnJson;
            }
            rtnJson.put("errorNo", "1");
        } catch (Exception e) {
            e.printStackTrace();
            rtnJson.put("errorNo", "1");
        }
        return rtnJson;
    }

    @Override
    public JSONObject orderList(OrderMobileDto orderMobileDto) {
        JSONObject rtnJson = new JSONObject();
        JSONObject object = new JSONObject();
        try {
            if (StringUtils.isEmpty(orderMobileDto.getOpenId())) {
                rtnJson.put("errorNo", "0");
                rtnJson.put("errorMsg", "openid不能为空");
                return rtnJson;
            }
            if (orderMobileDto.getStatus() == null) {
                rtnJson.put("errorNo", "0");
                rtnJson.put("errorMsg", "订单状态不能为空");
                return rtnJson;
            }
            MpAccountsEntity mpAccountsAppid = mpAccountsService.getMpAccountsAppid(orderMobileDto.getAppId());
            List<OrderMobile> orderMobiles = orderMapper.orderList(orderMobileDto);
            for (OrderMobile orderMobile : orderMobiles) {
                Long mobileId = orderMobile.getId();
                if (mobileId != null) {
                    List<ProductMobile> mobiles = orderMapper.orderDetill(mobileId);
                    orderMobile.setProductMobile(mobiles);
                }
            }
            object.put("orderMobiles", orderMobiles);
            rtnJson.put("errorNo", "0");
            rtnJson.put("data", object);
        } catch (Exception e) {
            e.printStackTrace();
            rtnJson.put("errorNo", "1");
        }
        return rtnJson;
    }

    @Override
    public Integer isThreeUsers(String openid) {
        return orderMapper.isThreeUsers(openid);
    }

    @Override
    public JSONObject invoice(InvoiceDto invoiceDto) {
        JSONObject jsonObject = new JSONObject();
        MpAccountsEntity mpAccountsEntity = null;
        if (StringUtils.isNotBlank(invoiceDto.getAppId())){
             mpAccountsEntity = mpAccountsService.getMpAccountsAppid(invoiceDto.getAppId());
        }else{
            jsonObject.put("errorNo","2");
            jsonObject.put("errorMsg","appId不能为空");
            return jsonObject;
        }

        try {
            Conds conds = new Conds();
            conds.equal("o.id", invoiceDto.getId());
            conds.equal("o.del_flag", Constants.DEL_FLAG_0);
            List<Order> list = this.fetchSearchBy(conds, null, 0, 0, null);
            if(list.size() > 0){
                for (Order order : list){
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    order.setCreateTimeStr(format.format(order.getCreateTime()));

                    //抬头类型为企业设置发票税号
                    String unitTax = null;
                    if(invoiceDto.getType().equals("1")){
                       unitTax = invoiceDto.getUnitTaxNumber();
                    }

                    String str = invoiceUtil.startInvoice(order,order.getNickName(),invoiceDto.getEmail(),invoiceDto.getType(),"0",unitTax);
                    JSONObject json = JSON.parseObject(str);
                    if ( org.apache.commons.lang3.StringUtils.isNotBlank(json.getString("code")) && json.getString("code").equals("E0000")){
                        //开票成功 添加一条开票记录
                        //流水号
                        String invoiceSerialNum = json.getJSONObject("result").getString("invoiceSerialNum");
                        Invoice invoice = new Invoice();
                        //发票抬头
                        if(invoiceDto.getType().equals("1")){
                            //抬头类型为公司则发票税号
                            invoice.setUnitTaxNumber(invoiceDto.getUnitTaxNumber());
                        }
                        invoice.setNumber(codingruleUtils.getNumber(mpAccountsEntity.getId(), Invoice.class.getName()));
                        invoice.setInvoiceTitle(invoiceDto.getInvoiceTitle());
                        invoice.setInvoiceContent(invoiceDto.getInvoiceContent());
                        invoice.setInvoiceType("1");
                        invoice.setInvoiceForm("1");
                        invoice.setClerkId(order.getMemberName());
                        invoice.setOrderId(order.getNumber());
                        invoice.setPushMode("0");
                        invoice.setEmail(invoiceDto.getEmail());
                        invoice.setStatus("0");
                        invoice.setInvoiceSerialNum(invoiceSerialNum);
                        invoice.setAccountsId(mpAccountsEntity.getId());
                        invoice.setOpenId(order.getOpenid());
                        invoice.setOperator(order.getNickName());
                        invoiceService.save(invoice);

                        //更新是否开票状态
                        order.setConfirm(invoiceSerialNum);
                        orderMapper.update(order);
                    }else{
                        jsonObject.put("errorNo", 1);
                        jsonObject.put("errorMsg", org.apache.commons.lang3.StringUtils.isEmpty(json.getString("describe")) ? json.getString("message") : json.getString("describe"));
                        return jsonObject;
                    }
                }
            }
            jsonObject.put("errorNo", 0);
        }catch (Exception e){
            e.printStackTrace();
            jsonObject.put("errorNo","1");
            jsonObject.put("errorMsg","程序异常");
        }
        return jsonObject;
    }

    @Override
    public Integer updateRemindType(Long id, String option) {
        return orderMapper.updateRemindType(id, option);
    }

    @Transactional
    @Override
    public String callBackPayStatus(HttpServletRequest request) {
        try {
            TreeMap<String, String> map = WechatPayUtils.parseXml(request);
            String result = JSONUtils.toJSONString(map);
            log.info("callBackPayStatus 支付详情 =" + result);
            if (StringUtils.equals(map.get("return_code"), "SUCCESS") && StringUtils.equals(map.get("result_code"), "SUCCESS")) {
                String appid = map.get("appid");
                String mch_id = map.get("mch_id");
                String out_trade_no = map.get("out_trade_no");//订单编码
                String transaction_id = map.get("transaction_id");//微信订单支付号
                String time_end = map.get("time_end");//订单完成时间
                if (StringUtils.equals(appid, SystemConfig.p.getProperty("WX_MP_SERVER_APPID")) && StringUtils.equals(mch_id, SystemConfig.p.getProperty("mch.mch_id"))) {
                    Conds orderConds = new Conds();
                    orderConds.equal("o.del_flag", Constants.DEL_FLAG_0);
                    orderConds.equal("o.number", out_trade_no);
                    Order order = this.fetchSearchByConds(orderConds);
                    //付款时间
                    if (order != null) {
                        order.setPayStatus(result);
                        order.setStatus("2");//待发货
                        order.setTradeNo(transaction_id);
                        //订单总金额
                        if (StringUtils.isNoneBlank(map.get("total_fee"))) {
                            order.setTotalAmount(Double.parseDouble(map.get("total_fee")));
                        }
                        //现金支付总金额
                        if (StringUtils.isNoneBlank(map.get("cash_fee"))) {
                            order.setPayAmount(Double.parseDouble(map.get("cash_fee")));
                        }
                        //支付完成时间
                        if (StringUtils.isNoneBlank(time_end)) {
                            Date date = DateFormatUtils.formatDate(time_end, "yyyyMMddHHmmss");
                            order.setPayTime(date);
                        }
                        if (orderMapper.update(order) > 0) {
                            sendQyWechatMassage(order.getId());
                            return WechatPayUtils.retSucXml;
                        }
                    } else {
                        log.info("callBackPayStatus 支付回调失败！订单不存在 orderNumber=" + transaction_id);
                    }
                } else {
                    log.info("callBackPayStatus 支付回调失败！appid/mchid返回失败");
                }
            } else {
                log.info("callBackPayStatus 支付回调失败！接口返回失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("callBackPayStatus 支付回调失败！ message = " + e.getMessage());
            return WechatPayUtils.retFailXml;
        }
        return WechatPayUtils.retFailXml;
    }

    @Override
    public String findOrderPayParams(String orderId, String openId, String appId, String prepayId) {
        JSONObject retObj = new JSONObject();

        try {
            MpAccountsEntity mpAccountsEntity = mpAccountsService.getMpAccountsAppid(appId);
            if (mpAccountsEntity == null) {
                retObj.put("errorNo", 1);
                retObj.put("errorMsg", "公众号信息获取失败!");
                return retObj.toString();
            }

            //获取待付款订单
            Conds orderConds = new Conds();
            orderConds.equal("o.del_flag", Constants.DEL_FLAG_0);
            orderConds.equal("o.status", "1");
            orderConds.equal("o.id", orderId);
            Order order = this.fetchSearchByConds(orderConds);
            if (order == null) {
                retObj.put("errorNo", 1);
                retObj.put("errorMsg", "订单信息获取失败!");
                return retObj.toString();
            }

            MpFanssEntity fanssEntity = mpFanssService.getWxUser(openId);
            if (fanssEntity == null) {
                retObj.put("errorNo", 1);
                retObj.put("errorMsg", "粉丝信息获取失败!");
                return retObj.toString();
            }

            JSONObject payParams = new JSONObject();
            payParams.put("appId", mpAccountsEntity.getAppid());
            payParams.put("timeStamp", Long.toString(System.currentTimeMillis() / 1000));
            payParams.put("nonceStr", UUID.randomUUID().toString().replaceAll("-", ""));
            payParams.put("package", "prepay_id=" + prepayId);
            payParams.put("signType", "MD5");

            SortedMap<String, String> params = new TreeMap<>();
            Iterator it = payParams.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
                params.put(entry.getKey(), entry.getValue());
            }

            String sign = WechatPayUtils.getSign(params, true);
            payParams.put("paySign", sign);

            retObj.put("errorNo", 0);
            retObj.put("data", payParams);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("下单接口获取订单信息失败！ error msg = " + e.getMessage());
        }
        return retObj.toString();
    }

    @Override
    public boolean sendQyWechatMassage(Long orderId) {
        Long accounts = Long.parseLong(SystemConfig.p.getProperty("QY_SEND_APPID"));
        MpAccountsEntity accountsEntity = mpAccountsService.getDetail(accounts);
        Long agenId = Long.parseLong(accountsEntity.getAgentId());

        Conds orderConds = new Conds();
        orderConds.equal("o.del_flag", Constants.DEL_FLAG_0);
        orderConds.equal("o.id", orderId);
        List<Order> orders = this.fetchSearchByPage(orderConds, null, 0, 0);
        if (orders == null || orders.size() != 1) {
            return false;
        }

        Conds qyuserConds = new Conds();
        qyuserConds.equal("t.del_flag", Constants.DEL_FLAG_0);
        qyuserConds.equal("t.user_type", "4");//订单员职业
        List<Qyuser> qyusers = qyuserService.fetchSearchByPage(qyuserConds, null, 0, 0);
        if (qyusers == null || qyusers.size() <= 0) {
            return false;
        }

        //推送客服消息
        Order order = orders.get(0);
        String msg = SystemConfig.p.getProperty("QY_SEND_ORDERCLERK_MSG") + order.getNumber();

        qyMsgUtil.sendText(accounts, false, qyusers, null, null, agenId, msg, false);
        return true;
    }

}