package com.gxwebsoft.common.system.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.RequestUtil;
import com.gxwebsoft.common.core.web.*;
import com.gxwebsoft.common.core.service.PaymentCacheService;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.entity.UserBalanceLog;
import com.gxwebsoft.common.system.param.PaymentParam;
import com.gxwebsoft.common.system.service.PaymentService;
import com.gxwebsoft.common.system.service.UserBalanceLogService;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.partnerpayments.model.TransactionAmount;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.gxwebsoft.common.core.constants.BalanceConstants.BALANCE_USE;

/**
 * 支付方式控制器
 *
 * @author 科技小王子
 * @since 2024-05-11 12:39:11
 */
@Tag(name = "支付")
@RestController
@RequestMapping("/api/system/payment")
public class PaymentController extends BaseController {
    @Resource
    private PaymentService paymentService;
    @Resource
    private UserService userService;
    @Resource
    private UserBalanceLogService userBalanceLogService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RequestUtil requestUtil;
    @Resource
    private PaymentCacheService paymentCacheService;

    @Operation(summary = "余额支付接口")
    @PostMapping("/balancePay")
    public ApiResult<?> balancePay(@RequestBody ShopOrder order) {
      System.out.println("使用余额支付 >>> 订单信息 " + order);

      // 查询购买者信息
      final User buyer = userService.getById(order.getUserId());

      if (buyer.getBalance().compareTo(order.getPayPrice()) < 0) {
        return fail("余额不足");
      }

      // 扣除余额
      final BigDecimal subtract = buyer.getBalance().subtract(order.getTotalPrice());
//      final BigDecimal multiply = subtract.multiply(new BigDecimal(100));
      buyer.setBalance(subtract);
      final boolean updateUser = userService.updateUser(buyer);

      // 记录余额明细
      UserBalanceLog userBalanceLog = new UserBalanceLog();
      userBalanceLog.setUserId(buyer.getUserId());
      userBalanceLog.setScene(BALANCE_USE);
      userBalanceLog.setMoney(order.getPayPrice());
      BigDecimal balance = buyer.getBalance().add(order.getPayPrice());
      userBalanceLog.setBalance(balance);
      userBalanceLog.setComments(order.getMerchantName());
      userBalanceLog.setTransactionId(UUID.randomUUID().toString());
      userBalanceLog.setOrderNo(order.getOrderNo());
      final boolean save = userBalanceLogService.save(userBalanceLog);
      System.out.println("save = " + save);

      // 推送微信官方支付结果(携带租户ID的POST请求)
      final Transaction transaction = new Transaction();
      transaction.setOutTradeNo(order.getOrderNo());
      transaction.setTransactionId(order.getOrderNo());
      final TransactionAmount amount = new TransactionAmount();
      // 计算金额
      BigDecimal decimal = order.getTotalPrice();
      final BigDecimal multiply = decimal.multiply(new BigDecimal(100));
      // 将 BigDecimal 转换为 Integer
      Integer money = multiply.intValue();
      amount.setTotal(money);
      amount.setCurrency("CNY");
      transaction.setAmount(amount);
      // 获取支付配置信息用于解密 - 使用缓存服务
      Payment payment = paymentCacheService.getWechatPayConfig(order.getTenantId());
      System.out.println("获取到支付配置: " + payment.getMchId());
      requestUtil.pushBalancePayNotify(transaction, payment);

      return success("支付成功",order.getOrderNo());
    }

    @Operation(summary = "选择支付方式")
    @GetMapping("/select")
    public ApiResult<?> select(PaymentParam param) {
      String key = "SelectPayment:".concat(getTenantId().toString());
      final String string = redisUtil.get(key);
      final List<Payment> paymentList = JSONObject.parseArray(string, Payment.class);
      if (!CollectionUtils.isEmpty(paymentList)) {
        return success(paymentList);
      }
      // 使用关联查询
      final List<Payment> list = paymentService.list(new LambdaUpdateWrapper<Payment>().eq(Payment::getStatus, true));
      if (!CollectionUtils.isEmpty(list)) {
        list.forEach(d -> {
          d.setApiKey(null);
          d.setApiclientCert(null);
          d.setApiclientKey(null);
          d.setMerchantSerialNumber(null);
        });
      }
      redisUtil.set(key,list,1L, TimeUnit.DAYS);
      return success(list);
    }

    @PreAuthorize("hasAuthority('sys:payment:list')")
    @Operation(summary = "分页查询支付方式")
    @GetMapping("/page")
    public ApiResult<PageResult<Payment>> page(PaymentParam param) {
        // 使用关联查询
        return success(paymentService.pageRel(param));
    }

    @PreAuthorize("hasAuthority('sys:payment:list')")
    @Operation(summary = "查询全部支付方式")
    @GetMapping()
    public ApiResult<List<Payment>> list(PaymentParam param) {
        // 使用关联查询
        return success(paymentService.listRel(param));
    }

    @PreAuthorize("hasAuthority('sys:payment:list')")
    @Operation(summary = "根据id查询支付方式")
    @GetMapping("/{id}")
    public ApiResult<Payment> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(paymentService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('sys:payment:save')")
    @OperationLog
    @Operation(summary = "添加支付方式")
    @PostMapping()
    public ApiResult<?> save(@RequestBody Payment payment) {
        if (paymentService.count(new LambdaQueryWrapper<Payment>().eq(Payment::getCode,payment.getCode())) > 0) {
          return fail(payment.getName() + "已存在");
        }
        if (paymentService.save(payment)) {
            // 使用缓存服务统一管理缓存
            paymentCacheService.cachePaymentConfig(payment, getTenantId());
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('sys:payment:update')")
    @OperationLog
    @Operation(summary = "修改支付方式")
    @PutMapping()
    public ApiResult<?> update(@RequestBody Payment payment) {
        if (paymentService.updateById(payment)) {
            // 使用缓存服务统一管理缓存
            paymentCacheService.cachePaymentConfig(payment, getTenantId());
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:payment:remove')")
    @OperationLog
    @Operation(summary = "删除支付方式")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        final Payment payment = paymentService.getById(id);
        System.out.println("payment = " + payment);

        // 使用缓存服务统一管理缓存删除
        paymentCacheService.removePaymentConfig(payment.getCode(), getTenantId());
        if (paymentService.removeById(id)) {
          return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('sys:payment:save')")
    @OperationLog
    @Operation(summary = "批量添加支付方式")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<Payment> list) {
        if (paymentService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('sys:payment:update')")
    @OperationLog
    @Operation(summary = "批量修改支付方式")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<Payment> batchParam) {
        if (batchParam.update(paymentService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:payment:remove')")
    @OperationLog
    @Operation(summary = "批量删除支付方式")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (paymentService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

}
