package com.gxwebsoft.shop.controller;

import cn.binarywang.wx.miniapp.api.WxMaOrderShippingService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaOrderShippingServiceImpl;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.gxwebsoft.common.core.utils.RequestUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.consts.BalanceScene;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.param.MerchantOfflinePayParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.gxwebsoft.shop.consts.OrderPayType.PAY_TYPE_WECHAT;

/**
 * 商铺线下支付控制器
 *
 * @author 科技小王子
 * @since 2025-05-28 18:23:45
 */
@Api(tags = "商铺线下支付管理")
@RestController
@RequestMapping("/api/shop/merchant-offline-pay")
public class MerchantOfflinePayController extends BaseController {
    @Resource
    private MerchantOfflinePayService merchantOfflinePayService;
    @Resource
    private OrderService orderService;
    @Resource
    private MerchantService merchantService;
    @Resource
    private RequestUtil requestUtil;
    @Resource
    private DealerCapitalService dealerCapitalService;
    @Resource
    private UserBalanceLogService userBalanceLogService;
    @Resource
    private WechatConfigService wechatConfigService;
    @Resource
    private MerchantVoiceDeviceService merchantVoiceDeviceService;
    @Autowired
    private WeChatController weChatController;

    @ApiModelProperty("微信支付通知")
    @PostMapping("/notify")
    public String notify(@RequestBody String body, @RequestHeader Map<String, Object> header) throws WxErrorException {
        com.wechat.pay.java.core.notification.RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(header.get("wechatpay-serial").toString())
                .nonce(header.get("wechatpay-nonce").toString())
                .signature(header.get("wechatpay-signature").toString())
                .timestamp(header.get("wechatpay-timestamp").toString())
                .body(body)
                .build();
        NotificationConfig config = wechatConfigService.getNotificationConfig();
        NotificationParser parser = new NotificationParser(config);
        com.wechat.pay.java.service.payments.model.Transaction transaction = parser.parse(requestParam, com.wechat.pay.java.service.payments.model.Transaction.class);
//        System.out.println("现场支付通知 >>>>> " + transaction);
        try {
            MerchantOfflinePay merchantOfflinePay = merchantOfflinePayService.getByOrderNo(transaction.getOutTradeNo());
            if (merchantOfflinePay != null) {
                if (merchantOfflinePay.getIsPaid().equals(0)) {
                    merchantOfflinePay.setIsPaid(1);
                    merchantOfflinePay.setPaidNumber(transaction.getTransactionId());
                    merchantOfflinePayService.updateById(merchantOfflinePay);

                    Merchant merchant = merchantService.getById(merchantOfflinePay.getMerchantId());
                    dealerCapitalService.save(new DealerCapital() {{
                        setUserId(merchant.getUserId());
                        setFlowType(10);
                        setMoney(merchantOfflinePay.getAmount());
                        setDescribe("门店现场支付");
                        setTenantId(getTenantId());
                        setStatus(1);
                    }});
                    requestUtil.setTenantId("10559");
                    User user = requestUtil.getByUserIdWithoutLogin(merchant.getUserId());
                    BigDecimal newBalance = user.getBalance().add(merchantOfflinePay.getAmount());
                    user.setBalance(newBalance);
                    requestUtil.updateUserBalanceWithoutLogin(user);

                    userBalanceLogService.save(new UserBalanceLog() {{
                        setUserId(merchant.getUserId());
                        setScene(BalanceScene.BALANCE_SCENE_MERCHANT_OFFLINE_PAY);
                        setMoney(merchantOfflinePay.getAmount());
                        setBalance(newBalance);
                        setMerchantId(merchantOfflinePay.getMerchantId());
                        setMerchantCode(merchant.getMerchantCode());
                        setOrderId(merchantOfflinePay.getId());
                        setTenantId(10559);
                    }});

                    List<MerchantVoiceDevice> merchantVoiceDeviceList = merchantVoiceDeviceService.listInMerchant(merchantOfflinePay.getMerchantId());
//                    System.out.println("商户播报设备: " + merchantVoiceDevice);
                    if (merchantVoiceDeviceList != null && !merchantVoiceDeviceList.isEmpty()) {
                        for (MerchantVoiceDevice merchantVoiceDevice1 : merchantVoiceDeviceList) {
                            Map<String, String> mapData = new HashMap<>();
                            mapData.put("agent_id", "202007291001");
                            mapData.put("agent_secret", "11476900311476900311476900311111");
                            mapData.put("sbx_id", merchantVoiceDevice1.getSbxId());
                            String msg = "收款" + merchantOfflinePay.getAmount().stripTrailingZeros().toPlainString() + "元";
                            if (merchantVoiceDevice1.getIs4g().equals(1)) {
                                if (merchantVoiceDevice1.getMsg() == null || merchantVoiceDevice1.getMsg().isEmpty()) {
                                    mapData.put("msg", msg);
                                } else {
                                    String customMsg = merchantVoiceDevice1.getMsg();
                                    String amountStr = merchantOfflinePay.getAmount().stripTrailingZeros().toPlainString();
                                    // 使用正则表达式进行不区分大小写的替换
                                    if (customMsg.matches(".*[xX].*")) {
                                        mapData.put("msg", customMsg.replaceAll("[xX]", amountStr));
                                    } else {
                                        mapData.put("msg", msg);
                                    }
                                }
                            }else mapData.put("msg", msg);
                            System.out.println("商户播报内容: " + mapData);
                            String res = HttpRequest.post("http://iot.solomo-info.com:9306/admin/common/msgpush")
                                    .body(JSONObject.toJSONString(mapData)).execute().body();
                            System.out.println("商户播报设备返回: " + res);
                        }
                    }

                    // 小程序发货
                    WxMaOrderShippingInfoUploadRequest uploadRequest = new WxMaOrderShippingInfoUploadRequest();
                    uploadRequest.setLogisticsType(3);
                    uploadRequest.setDeliveryMode(1);

                    OrderKeyBean orderKeyBean = new OrderKeyBean();
                    orderKeyBean.setOrderNumberType(2);
                    orderKeyBean.setTransactionId(transaction.getTransactionId());
                    uploadRequest.setOrderKey(orderKeyBean);

                    List<ShippingListBean> shippingList = new ArrayList<>();
                    ShippingListBean shippingListBean = new ShippingListBean();
                    String itemDesc = "牛八哥门店现点现付";
                    shippingListBean.setItemDesc(itemDesc);
                    shippingList.add(shippingListBean);
                    uploadRequest.setShippingList(shippingList);

                    uploadRequest.setUploadTime(new DateTime().toString(DatePattern.UTC_WITH_ZONE_OFFSET_PATTERN));

                    PayerBean payerBean = new PayerBean();
                    payerBean.setOpenid(user.getOpenid());
                    uploadRequest.setPayer(payerBean);

                    WxMaService wxMaService = weChatController.wxMaService();
                    WxMaOrderShippingService wxMaOrderShippingService = new WxMaOrderShippingServiceImpl(wxMaService);
                    WxMaOrderShippingInfoBaseResponse response = wxMaOrderShippingService.upload(uploadRequest);
                    System.out.println("offline pay response" + response);
                }
            }
        } catch (Exception e) {
            System.out.println("现场支付回调错误: " + e.getMessage());
        }
        return "支付成功";
    }

    @ApiOperation("分页查询商铺线下支付")
    @GetMapping("/page")
    public ApiResult<PageResult<MerchantOfflinePay>> page(MerchantOfflinePayParam param) {
        // 使用关联查询
        return success(merchantOfflinePayService.pageRel(param));
    }

    @ApiOperation("查询全部商铺线下支付")
    @GetMapping()
    public ApiResult<List<MerchantOfflinePay>> list(MerchantOfflinePayParam param) {
        // 使用关联查询
        param.setUserId(getLoginUserId());
        return success(merchantOfflinePayService.listRel(param));
    }

    @ApiOperation("查询全部商铺线下支付")
    @GetMapping("/forMerchant")
    public ApiResult<List<MerchantOfflinePay>> listForMerchant(MerchantOfflinePayParam param) {
        // 使用关联查询
        if (param.getMerchantId() == null) param.setMerchantId(getLoginUser().getMerchantId());
        return success(merchantOfflinePayService.listRel(param));
    }

    @PreAuthorize("hasAuthority('shop:merchantOfflinePay:list')")
    @ApiOperation("根据id查询商铺线下支付")
    @GetMapping("/{id}")
    public ApiResult<MerchantOfflinePay> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(merchantOfflinePayService.getByIdRel(id));
    }

    @ApiOperation("添加商铺线下支付")
    @PostMapping()
    public ApiResult<?> save(@RequestBody MerchantOfflinePay merchantOfflinePay) {
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser == null) return fail("请先登陆");
        merchantOfflinePay.setUserId(loginUser.getUserId());
        merchantOfflinePay.setOrderNo(RandomUtil.randomString(16));
        if (merchantOfflinePayService.save(merchantOfflinePay)) {
            Merchant merchant = merchantService.getById(merchantOfflinePay.getMerchantId());
            Order order = new Order();
            order.setTenantId(merchantOfflinePay.getTenantId());
            order.setPayType(PAY_TYPE_WECHAT);
            order.setTotalPrice(merchantOfflinePay.getAmount());
            order.setUserId(merchantOfflinePay.getUserId());
            order.setComments(merchant.getMerchantName() + "门店现场支付");
            order.setOrderNo(merchantOfflinePay.getOrderNo());
            order.setOpenid(loginUser.getOpenid());
            order.setNotifyUrl("https://ngb-service-api.websoft.top/api/shop/merchant-offline-pay/notify");
            return success("添加成功", orderService.createWxOrder(order));
        }
        return fail("添加失败");
    }

    @ApiOperation("修改商铺线下支付")
    @PutMapping()
    public ApiResult<?> update(@RequestBody MerchantOfflinePay merchantOfflinePay) {
        if (merchantOfflinePayService.updateById(merchantOfflinePay)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("删除商铺线下支付")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (merchantOfflinePayService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @ApiOperation("批量添加商铺线下支付")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<MerchantOfflinePay> list) {
        if (merchantOfflinePayService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @ApiOperation("批量修改商铺线下支付")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<MerchantOfflinePay> batchParam) {
        if (batchParam.update(merchantOfflinePayService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("批量删除商铺线下支付")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (merchantOfflinePayService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

}
