package com.gxwebsoft.clinic.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.clinic.entity.ClinicPrescription;
import com.gxwebsoft.clinic.entity.ClinicPrescriptionItem;
import com.gxwebsoft.clinic.entity.PrescriptionOrderItem;
import com.gxwebsoft.clinic.service.PrescriptionOrderItemService;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.utils.CertificateLoader;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.WechatPayConfigValidator;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.clinic.service.PrescriptionOrderService;
import com.gxwebsoft.clinic.entity.PrescriptionOrder;
import com.gxwebsoft.clinic.param.PrescriptionOrderParam;
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.Payment;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.service.OrderService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
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.ApiOperation;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 处方主表
 * 控制器
 *
 * @author LX
 * @since 2025-12-10 11:28:03
 */
@Api(tags = "处方主表")
@RestController
@RequestMapping("/api/clinic/prescription-order")
public class PrescriptionOrderController extends BaseController {
    @Resource
    private PrescriptionOrderService prescriptionOrderService;
    @Resource
    private PrescriptionOrderItemService prescriptionOrderItemService;
    @Resource
    private OrderService orderService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private WechatPayConfigValidator wechatPayConfigValidator;
    @Resource
    private CertificateProperties certConfig;
    @Resource
    private ConfigProperties config;

    @ApiOperation("分页查询处方主表")
    @GetMapping("/page")
    public ApiResult<PageResult<PrescriptionOrder>> page(PrescriptionOrderParam param) {
        // 使用关联查询
        return success(prescriptionOrderService.pageRel(param));
    }

    @ApiOperation("查询全部处方主表")
    @GetMapping()
    public ApiResult<List<PrescriptionOrder>> list(PrescriptionOrderParam param) {
        // 使用关联查询
        return success(prescriptionOrderService.listRel(param));
    }

    @ApiOperation("根据id查询处方主表")
    @GetMapping("/{id}")
    public ApiResult<PrescriptionOrder> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(prescriptionOrderService.getByIdRel(id));
    }

    @ApiOperation("添加处方主表")
    @PostMapping()
    public ApiResult<?> save(@RequestBody PrescriptionOrder prescriptionOrder) {
        prescriptionOrder.setDoctorId(getLoginUserId());
        // 生成订单号
        String orderNo = Long.toString(IdUtil.getSnowflakeNextId());
        prescriptionOrder.setOrderNo(orderNo);
        BigDecimal payPrice = prescriptionOrder.getOrderPrice();
        if (prescriptionOrder.getDecoctionAmount() != null)
            payPrice = payPrice.add(prescriptionOrder.getDecoctionAmount());
        if (prescriptionOrder.getExpressAmount() != null)
            payPrice = payPrice.add(prescriptionOrder.getExpressAmount());
        prescriptionOrder.setPayPrice(payPrice);
        if (prescriptionOrderService.save(prescriptionOrder)) {
            if (prescriptionOrder.getItems() != null && !prescriptionOrder.getItems().isEmpty()) {
                for (PrescriptionOrderItem item : prescriptionOrder.getItems()) {
                    item.setPrescriptionId(prescriptionOrder.getId());
                    item.setPrescriptionNo(orderNo);
                }
                prescriptionOrderItemService.saveBatch(prescriptionOrder.getItems());
            }
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @ApiOperation("修改处方主表")
    @PutMapping()
    public ApiResult<?> update(@RequestBody PrescriptionOrder prescriptionOrder) {
        if (prescriptionOrderService.updateById(prescriptionOrder)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("删除处方主表")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (prescriptionOrderService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @ApiOperation("批量添加处方主表")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<PrescriptionOrder> list) {
        if (prescriptionOrderService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @ApiOperation("批量修改处方主表")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<PrescriptionOrder> batchParam) {
        if (batchParam.update(prescriptionOrderService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("批量删除处方主表")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (prescriptionOrderService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PostMapping("/pay")
    public ApiResult<?> pay(@RequestBody PrescriptionOrder prescriptionOrderData) {
        PrescriptionOrder prescriptionOrder = prescriptionOrderService.getById(prescriptionOrderData.getId());
        Order order = new Order();
        order.setTenantId(getTenantId());
        order.setTotalPrice(prescriptionOrder.getPayPrice());
        order.setComments(prescriptionOrder.getOrderNo());
        order.setOrderNo(prescriptionOrder.getOrderNo());
        order.setOpenid(getLoginUser().getOpenid());
        order.setNotifyUrl("https://clinic-api.websoft.top/api/clinic/prescription-order/notify");
        return success("调起成功", orderService.createWxOrder(order));
    }

    @Schema(description = "异步通知")
    @PostMapping("/notify")
    public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body) {
        System.out.println("异步通知*************** =");

        String key = "Payment:1:10559";
        final String uploadPath = config.getUploadPath();
        final com.gxwebsoft.common.system.entity.Payment payment = redisUtil.get(key, Payment.class);
        String privateKeyPath = uploadPath.concat("/file").concat(payment.getApiclientKey());
        String apiclientCert = uploadPath.concat("/file").concat(payment.getApiclientCert());

        com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
                .serialNumber(header.get("wechatpay-serial"))
                .nonce(header.get("wechatpay-nonce"))
                .signature(header.get("wechatpay-signature"))
                .timestamp(header.get("wechatpay-timestamp"))
                .body(body)
                .build();

        // 如果已经初始化了 RSAAutoCertificateConfig，可直接使用
        // 没有的话，则构造一个
        NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                .merchantId(payment.getMchId())
                .privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(payment.getMerchantSerialNumber())
                .apiV3Key(payment.getApiKey())
                .build();

        // 初始化 NotificationParser
        NotificationParser parser = new NotificationParser(config);

        // 以支付通知回调为例，验签、解密并转换成 Transaction
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        System.out.println("transaction = " + transaction);

        if (StrUtil.equals("支付成功", transaction.getTradeStateDesc())) {
            final String outTradeNo = transaction.getOutTradeNo();
            final String transactionId = transaction.getTransactionId();
            final Integer total = transaction.getAmount().getTotal();
            final String tradeStateDesc = transaction.getTradeStateDesc();
            final Transaction.TradeStateEnum tradeState = transaction.getTradeState();
            final Transaction.TradeTypeEnum tradeType = transaction.getTradeType();

            PrescriptionOrder prescriptionOrder = prescriptionOrderService.getByOrderNo(outTradeNo);
            System.out.println("outTradeNo = " + outTradeNo);
            System.out.println("clinicPrescription = " + prescriptionOrder);
            if (prescriptionOrder != null) {
                prescriptionOrder.setStatus(1);
                prescriptionOrderService.updateById(prescriptionOrder);
            }
            return "SUCCESS";
        }

        return "fail";
    }

}
