package com.gxwebsoft.shop.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
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.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.CertificateLoader;
import com.gxwebsoft.common.core.utils.WechatCertAutoConfig;
import com.gxwebsoft.common.core.utils.WechatPayConfigValidator;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.gxwebsoft.shop.service.OrderBusinessService;
import com.gxwebsoft.shop.service.OrderCancelService;
import com.gxwebsoft.shop.task.OrderAutoCancelTask;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.shop.dto.OrderCreateRequest;
import com.gxwebsoft.shop.dto.UpdatePaymentStatusRequest;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
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.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

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

/**
 * 订单控制器
 *
 * @author 科技小王子
 * @since 2025-01-11 10:45:12
 */
@Tag(name = "订单管理")
@RestController
@RequestMapping("/api/shop/shop-order")
public class ShopOrderController extends BaseController {
  private static final Logger logger = LoggerFactory.getLogger(ShopOrderController.class);
  @Resource
  private ShopOrderService shopOrderService;
  @Resource
  private ShopOrderGoodsService shopOrderGoodsService;
  @Resource
  private OrderBusinessService orderBusinessService;
  @Resource
  private OrderCancelService orderCancelService;
  @Resource
  private OrderAutoCancelTask orderAutoCancelTask;
  @Resource
  private RedisUtil redisUtil;
  @Resource
  private ConfigProperties conf;
  @Resource
  private CertificateProperties certConfig;
  @Resource
  private CertificateLoader certificateLoader;
  @Resource
  private WechatCertAutoConfig wechatCertAutoConfig;
  @Resource
  private WechatPayConfigValidator wechatPayConfigValidator;
  @Value("${spring.profiles.active}")
  String active;

  @Operation(summary = "分页查询订单")
  @GetMapping("/page")
  public ApiResult<PageResult<ShopOrder>> page(ShopOrderParam param) {
    // 使用关联查询
    return success(shopOrderService.pageRel(param));
  }

  @Operation(summary = "查询全部订单")
  @GetMapping()
  public ApiResult<List<ShopOrder>> list(ShopOrderParam param) {
    // 使用关联查询
    return success(shopOrderService.listRel(param));
  }

  @PreAuthorize("hasAuthority('shop:shopOrder:list')")
  @Operation(summary = "根据id查询订单")
  @GetMapping("/{id}")
  public ApiResult<ShopOrder> get(@PathVariable("id") Integer id) {
    // 使用关联查询
    return success(shopOrderService.getByIdRel(id));
  }

  @Operation(summary = "添加订单")
  @PostMapping()
  public ApiResult<?> save(@RequestBody OrderCreateRequest request) {
    User loginUser = getLoginUser();
    if (loginUser == null) {
      return fail("用户未登录");
    }

    try {
      Map<String, String> wxOrderInfo = orderBusinessService.createOrder(request, loginUser);
      return success("下单成功", wxOrderInfo);
    } catch (Exception e) {
      logger.error("创建订单失败 - 用户ID：{}，请求：{}", loginUser.getUserId(), request, e);
      return fail(e.getMessage());
    }
  }

  @Operation(summary = "添加订单(兼容旧版本)")
  @PostMapping("/legacy")
  public ApiResult<?> saveLegacy(@RequestBody ShopOrder shopOrder) {
    // 记录当前登录用户id
    User loginUser = getLoginUser();
    if (loginUser != null) {
      shopOrder.setUserId(loginUser.getUserId());
      shopOrder.setOpenid(loginUser.getOpenid());
      shopOrder.setPayUserId(loginUser.getUserId());
      if (shopOrder.getOrderNo() == null) {
        shopOrder.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
      }
      if (shopOrder.getComments() == null) {
        shopOrder.setComments("暂无");
      }
      // 微信支付(商品金额不能为0)
      if (shopOrder.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
        return fail("商品金额不能为0");
      }
      // 百色中学项目捐赠金额不能低于20元
      if (shopOrder.getTenantId().equals(10324) && shopOrder.getTotalPrice().compareTo(new BigDecimal("10")) < 0) {
        return fail("捐款金额最低不能少于10元，感谢您的爱心捐赠^_^");
      }
      // 测试支付
      if (loginUser.getPhone().equals("13737128880")) {
        shopOrder.setPrice(new BigDecimal("0.01"));
        shopOrder.setTotalPrice(new BigDecimal("0.01"));
      }
      if (shopOrderService.save(shopOrder)) {
        return success("下单成功", shopOrderService.createWxOrder(shopOrder));
      }
    }
    return fail("添加失败");
  }

  @PreAuthorize("hasAuthority('shop:shopOrder:update')")
  @Operation(summary = "修改订单")
  @PutMapping()
  public ApiResult<?> update(@RequestBody ShopOrder shopOrder) {
    // 申请退款
    if(shopOrder.getOrderStatus().equals(4)){
      shopOrder.setRefundApplyTime(LocalDateTime.now());
    }
    if (shopOrderService.updateById(shopOrder)) {
      return success("修改成功");
    }
    return fail("修改失败");
  }

  @Operation(summary = "删除订单")
  @DeleteMapping("/{id}")
  public ApiResult<?> remove(@PathVariable("id") Integer id) {
    if (shopOrderService.removeById(id)) {
      return success("删除成功");
    }
    return fail("删除失败");
  }

  @Operation(summary = "批量添加订单")
  @PostMapping("/batch")
  public ApiResult<?> saveBatch(@RequestBody List<ShopOrder> list) {
    if (shopOrderService.saveBatch(list)) {
      return success("添加成功");
    }
    return fail("添加失败");
  }

  @Operation(summary = "批量修改订单")
  @PutMapping("/batch")
  public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopOrder> batchParam) {
    if (batchParam.update(shopOrderService, "order_id")) {
      return success("修改成功");
    }
    return fail("修改失败");
  }

  @Operation(summary = "批量删除订单")
  @DeleteMapping("/batch")
  public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
    if (shopOrderService.removeByIds(ids)) {
      return success("删除成功");
    }
    return fail("删除失败");
  }

  @Operation(summary = "修复订单")
  @PutMapping("/repair")
  public ApiResult<?> repair(@RequestBody ShopOrder shopOrder) {
    final ShopOrder order = shopOrderService.getByOutTradeNo(shopOrder.getOrderNo());
    if(order != null){
      shopOrderService.queryOrderByOutTradeNo(order);
      return success("修复成功");
    }
    return fail("修复失败");
  }

  @Operation(summary = "统计订单总金额")
  @GetMapping("/total")
  public ApiResult<BigDecimal> total() {
    return success(shopOrderService.total());
  }

  @Operation(summary = "取消订单")
  @PutMapping("/cancel/{id}")
  public ApiResult<?> cancelOrder(@PathVariable("id") Integer id) {
    try {
      User loginUser = getLoginUser();
      if (loginUser == null) {
        return fail("用户未登录");
      }

      ShopOrder order = shopOrderService.getById(id);
      if (order == null) {
        return fail("订单不存在");
      }

      // 检查订单是否属于当前用户（非管理员用户）
      if (!loginUser.getUserId().equals(order.getUserId()) &&
          !hasOrderCancelAuthority()) {
        return fail("无权限取消此订单");
      }

      // 检查订单状态
      if (order.getPayStatus() != null && order.getPayStatus()) {
        return fail("订单已支付，无法取消");
      }

      if (order.getOrderStatus() != null && order.getOrderStatus() != 0) {
        return fail("订单状态不允许取消");
      }

      boolean success = orderCancelService.cancelOrder(order);
      if (success) {
        return success("订单取消成功");
      } else {
        return fail("订单取消失败");
      }

    } catch (Exception e) {
      logger.error("取消订单失败，订单ID：{}", id, e);
      return fail("取消订单失败：" + e.getMessage());
    }
  }

  @PreAuthorize("hasAuthority('shop:shopOrder:manage')")
  @Operation(summary = "手动触发订单自动取消任务（管理员）")
  @PostMapping("/auto-cancel/trigger")
  public ApiResult<?> triggerAutoCancelTask() {
    try {
      orderAutoCancelTask.manualCancelExpiredOrders();
      return success("自动取消任务已触发");
    } catch (Exception e) {
      logger.error("触发自动取消任务失败", e);
      return fail("触发失败：" + e.getMessage());
    }
  }

  @PreAuthorize("hasAuthority('shop:shopOrder:manage')")
  @Operation(summary = "获取自动取消任务状态（管理员）")
  @GetMapping("/auto-cancel/status")
  public ApiResult<?> getAutoCancelTaskStatus() {
    try {
      String status = orderAutoCancelTask.getTaskStatus();
      return success(status);
    } catch (Exception e) {
      logger.error("获取自动取消任务状态失败", e);
      return fail("获取状态失败：" + e.getMessage());
    }
  }

  @Schema(description = "异步通知11")
  @PostMapping("/notify/{tenantId}")
  public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) {
    logger.info("异步通知*************** = " + tenantId);

    // 获取支付配置信息用于解密
    String key = "Payment:1:".concat(tenantId.toString());
    Payment payment = redisUtil.get(key, Payment.class);

    // 检查支付配置
    if (ObjectUtil.isEmpty(payment)) {
      throw new RuntimeException("未找到租户支付配置信息，租户ID: " + tenantId);
    }

    logger.info("开始处理微信支付异步通知 - 租户ID: {}", tenantId);
    logger.info("支付配置信息 - 商户号: {}, 应用ID: {}", payment.getMchId(), payment.getAppId());

    // 验证微信支付配置
    WechatPayConfigValidator.ValidationResult validation = wechatPayConfigValidator.validateWechatPayConfig(payment, tenantId);
    if (!validation.isValid()) {
      logger.error("❌ 微信支付配置验证失败: {}", validation.getErrors());
      logger.info("📋 配置诊断报告:\n{}", wechatPayConfigValidator.generateDiagnosticReport(payment, tenantId));
      throw new RuntimeException("微信支付配置验证失败: " + validation.getErrors());
    }
    logger.info("✅ 微信支付配置验证通过");

    RequestParam requestParam = new 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();

    // 创建通知配置 - 使用与下单方法相同的证书配置逻辑
    NotificationConfig config;
    try {
      if (active.equals("dev")) {
        // 开发环境 - 构建包含租户号的私钥路径
        String tenantCertPath = "dev/wechat/" + tenantId;
        String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();

        logger.info("开发环境异步通知证书路径: {}", privateKeyPath);
        logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath);

        // 检查证书文件是否存在
        if (!certificateLoader.certificateExists(privateKeyPath)) {
          logger.error("证书文件不存在: {}", privateKeyPath);
          throw new RuntimeException("证书文件不存在: " + privateKeyPath);
        }

        String privateKey = certificateLoader.loadCertificatePath(privateKeyPath);

        // 使用验证器获取有效的 APIv3 密钥
        String apiV3Key = wechatPayConfigValidator.getValidApiV3Key(payment);

        logger.info("私钥文件加载成功: {}", privateKey);
        logger.info("使用APIv3密钥来源: {}", payment.getApiKey() != null && !payment.getApiKey().trim().isEmpty() ? "数据库配置" : "配置文件默认");
        logger.info("APIv3密钥长度: {}", apiV3Key != null ? apiV3Key.length() : 0);
        logger.info("商户证书序列号: {}", payment.getMerchantSerialNumber());

        // 使用自动证书配置
        config = new RSAAutoCertificateConfig.Builder()
          .merchantId(payment.getMchId())
          .privateKeyFromPath(privateKey)
          .merchantSerialNumber(payment.getMerchantSerialNumber())
          .apiV3Key(apiV3Key)
          .build();

        logger.info("✅ 开发环境使用自动证书配置创建通知解析器成功");
      } else {
        // 生产环境 - 使用自动证书配置
        final String certRootPath = certConfig.getCertRootPath();
        logger.info("生产环境证书根路径: {}", certRootPath);

        String privateKeyRelativePath = payment.getApiclientKey();
        logger.info("数据库中的私钥相对路径: {}", privateKeyRelativePath);

        // 修复路径拼接逻辑：数据库中存储的路径如果已经包含 /file，则直接拼接
        String privateKeyFullPath;
        if (privateKeyRelativePath.startsWith("/file/")) {
            // 路径已经包含 /file/ 前缀，直接拼接到根路径
            privateKeyFullPath = certRootPath + privateKeyRelativePath;
        } else if (privateKeyRelativePath.startsWith("file/")) {
            // 路径包含 file/ 前缀，添加根路径和斜杠
            privateKeyFullPath = certRootPath + "/" + privateKeyRelativePath;
        } else {
            // 路径不包含 file 前缀，添加完整的 /file/ 前缀
            privateKeyFullPath = certRootPath + "/file/" + privateKeyRelativePath;
        }

        logger.info("生产环境私钥完整路径: {}", privateKeyFullPath);
        String privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
        String apiV3Key = payment.getApiKey();

        // 使用自动证书配置
        config = new RSAAutoCertificateConfig.Builder()
          .merchantId(payment.getMchId())
          .privateKeyFromPath(privateKey)
          .merchantSerialNumber(payment.getMerchantSerialNumber())
          .apiV3Key(apiV3Key)
          .build();

        logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功");
      }
    } catch (Exception e) {
      logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
      logger.error("🔍 错误详情: {}", e.getMessage());
      logger.error("💡 请检查:");
      logger.error("1. 证书文件是否存在且路径正确");
      logger.error("2. APIv3密钥是否配置正确");
      logger.error("3. 商户证书序列号是否正确");
      logger.error("4. 网络连接是否正常");
      throw new RuntimeException("微信支付通知配置失败: " + e.getMessage(), e);
    }

    // 初始化 NotificationParser
    NotificationParser parser = new NotificationParser(config);
    logger.info("✅ 通知解析器创建成功，准备解析异步通知");

    // 以支付通知回调为例，验签、解密并转换成 Transaction
    try {
      logger.info("开始解析微信支付异步通知...");
      Transaction transaction = parser.parse(requestParam, Transaction.class);
      logger.info("✅ 异步通知解析成功 - 交易状态: {}, 商户订单号: {}",
                  transaction.getTradeStateDesc(), transaction.getOutTradeNo());

      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();
        System.out.println("transaction = " + transaction);
        System.out.println("tradeStateDesc = " + tradeStateDesc);
        System.out.println("tradeType = " + tradeType);
        System.out.println("tradeState = " + tradeState);
        System.out.println("outTradeNo = " + outTradeNo);
        System.out.println("amount = " + total);
        // 1. 查询要处理的订单
        ShopOrder order = shopOrderService.getByOutTradeNo(outTradeNo);
        logger.info("查询要处理的订单order = " + order);
        // 2. 已支付则跳过
        if (order.getPayStatus().equals(true)) {
          return "SUCCESS";
        }
        // 2. 未支付则处理更新订单状态
        if (order.getPayStatus().equals(false)) {
          // 5. TODO 处理订单状态
          order.setPayTime(LocalDateTime.now());
          order.setExpirationTime(order.getCreateTime());
          order.setPayStatus(true);
          order.setTransactionId(transactionId);
          order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", total * 0.01)));
          order.setExpirationTime(LocalDateTime.now().plusYears(10));
          System.out.println("实际付款金额 = " + order.getPayPrice());
          // 更新订单状态并处理支付成功后的业务逻辑（包括累加商品销量）
          shopOrderService.updateByOutTradeNo(order);
          return "SUCCESS";
        }
      }
    } catch (Exception e) {
      logger.error("❌ 处理微信支付异步通知失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
      logger.error("🔍 异常详情: {}", e.getMessage());
      logger.error("💡 可能的原因:");
      logger.error("1. 证书配置错误或证书文件损坏");
      logger.error("2. 微信支付平台证书已过期");
      logger.error("3. 签名验证失败");
      logger.error("4. 请求参数格式错误");

      // 返回失败，微信会重试
      return "fail";
    }

    logger.warn("⚠️ 异步通知处理完成但未找到匹配的支付成功状态");
    return "fail";
  }

  @Operation(summary = "更新订单支付状态", description = "用户支付成功后主动同步订单状态")
  @PutMapping("/payment-status")
  public ApiResult<?> updateOrderPaymentStatus(@RequestBody UpdatePaymentStatusRequest request) {
    logger.info("收到更新订单支付状态请求: orderNo={}, paymentStatus={}, transactionId={}",
        request.getOrderNo(), request.getPaymentStatus(), request.getTransactionId());

    final User loginUser = getLoginUser();
    if (loginUser == null) {
      return fail("请先登录");
    }

    try {
      // 参数验证
      if (StrUtil.isBlank(request.getOrderNo())) {
        return fail("订单号不能为空");
      }

      // 查询订单
      ShopOrder order = shopOrderService.getByOrderNo(request.getOrderNo(), loginUser.getTenantId());
      if (order == null) {
        return fail("订单不存在");
      }

      // 权限验证：只能更新自己的订单
      if (!order.getUserId().equals(loginUser.getUserId())) {
        return fail("无权限操作此订单");
      }

      // 如果订单已经是支付成功状态，直接返回成功
      if (order.getPayStatus()) {
        logger.info("订单已经是支付成功状态，无需更新: orderNo={}", request.getOrderNo());
        return success("订单状态已是最新");
      }

      // 调用支付状态同步服务
      boolean updated = shopOrderService.syncPaymentStatus(
          request.getOrderNo(),
          request.getPaymentStatus(),
          request.getTransactionId(),
          request.getPayTime(),
          loginUser.getTenantId()
      );

      if (updated) {
        logger.info("订单支付状态更新成功: orderNo={}, paymentStatus={}",
            request.getOrderNo(), request.getPaymentStatus());
        return success("订单状态更新成功");
      } else {
        logger.warn("订单支付状态更新失败: orderNo={}", request.getOrderNo());
        return fail("订单状态更新失败");
      }

    } catch (Exception e) {
      logger.error("更新订单支付状态异常: orderNo={}, error={}", request.getOrderNo(), e.getMessage(), e);
      return fail("更新订单状态失败: " + e.getMessage());
    }
  }

  /**
   * 检查是否有订单取消权限
   */
  private boolean hasOrderCancelAuthority() {
    try {
      Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
      if (authentication == null) {
        return false;
      }

      // 检查是否有管理员权限
      return authentication.getAuthorities().stream()
              .anyMatch(authority ->
                      authority.getAuthority().equals("shop:shopOrder:cancel") ||
                      authority.getAuthority().equals("shop:shopOrder:update") ||
                      authority.getAuthority().equals("ROLE_ADMIN") ||
                      authority.getAuthority().equals("shop:shopOrder:manage"));
    } catch (Exception e) {
      logger.warn("检查订单取消权限时发生异常", e);
      return false;
    }
  }

}
