package com.haha.miniapp.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import com.haha.common.constant.CallbackConstants;
import com.haha.common.utils.RequestParseUtil;
import com.haha.common.vo.Result;
import com.haha.service.payment.payscore.PayScoreCallbackResult;
import com.haha.service.payment.payscore.PayScoreModifyRequest;
import com.haha.service.payment.payscore.PayScoreResult;
import com.haha.service.payment.payscore.PayScoreService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 微信支付分控制器
 * 需确认模式：每次服务开门前预创建支付分订单，用户确认后开门
 */
@Slf4j
@RestController
@RequestMapping("/payscore")
@RequiredArgsConstructor
public class PayScoreController {

    private final PayScoreService payScoreService;

    /**
     * 获取微信支付分订单详情页签名参数
     * 供前端调用 wx.openBusinessView({ businessType: 'wxpayScoreDetail' }) 拉起订单详情
     */
    @PostMapping("/detail-sign")
    public Result<Map<String, Object>> getPayscoreDetailSign(@RequestBody Map<String, Object> params) {
        try {
            if (!params.containsKey("outOrderNo")) {
                return com.haha.common.constant.ResponseEnum.PARAM_FORMAT_ERROR.toResult("缺少必填参数 outOrderNo");
            }
            String outOrderNo = params.get("outOrderNo").toString();
            Map<String, Object> data = payScoreService.getPayscoreDetailSign(outOrderNo);
            return Result.success(data);
        } catch (Exception e) {
            log.error("获取支付分详情签名失败", e);
            return Result.error("获取签名失败：" + e.getMessage());
        }
    }

    /**
     * 预创建支付分服务订单（需确认模式，开门前调用）
     * 返回 package 参数供前端调用 wx.openBusinessView 拉起确认页
     */
    @PostMapping("/pre-create")
    public Result<Map<String, Object>> preCreatePayScoreOrder(@RequestBody Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();

            if (!params.containsKey("deviceId")) {
                return com.haha.common.constant.ResponseEnum.PARAM_FORMAT_ERROR.toResult("缺少必填参数 deviceId");
            }

            String deviceId = params.get("deviceId").toString();

            log.info("用户 {} 预创建支付分服务订单 - deviceId: {}", userId, deviceId);

            Map<String, Object> data = payScoreService.preCreatePayScoreOrder(userId, deviceId, null);
            if (Boolean.TRUE.equals(data.get("success"))) {
                return Result.success("创建成功", data);
            } else {
                return Result.error(String.valueOf(data.get("errorMsg")));
            }
        } catch (Exception e) {
            log.error("预创建支付分订单失败", e);
            return Result.error("创建失败：" + e.getMessage());
        }
    }

    /**
     * 创建支付分服务订单
     */
    @PostMapping("/create")
    public Result<Map<String, Object>> createPayScoreOrder(@RequestBody Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 请求创建支付分服务订单", userId);

            Map<String, Object> data = payScoreService.createUserPayScoreOrder(userId, params);
            if (data != null) {
                log.info("创建支付分服务订单成功 - orderId: {}", params.get("orderId"));
                return Result.success("创建成功", data);
            } else {
                return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("创建支付分服务订单失败");
            }
        } catch (NumberFormatException e) {
            log.error("参数格式错误", e);
            return com.haha.common.constant.ResponseEnum.PARAM_FORMAT_ERROR.toResult();
        } catch (Exception e) {
            log.error("创建支付分服务订单失败", e);
            return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("创建失败：" + e.getMessage());
        }
    }

    /**
     * 完结支付分服务订单
     */
    @PostMapping("/complete")
    public Result<Map<String, Object>> completePayScoreOrder(@RequestBody Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 请求完结支付分服务订单", userId);

            Map<String, Object> data = payScoreService.completeUserPayScoreOrder(userId, params);
            if (data != null) {
                log.info("完结支付分服务订单成功 - orderId: {}", params.get("orderId"));
                return Result.success("完结成功", data);
            } else {
                return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("完结支付分服务订单失败");
            }
        } catch (NumberFormatException e) {
            log.error("参数格式错误", e);
            return com.haha.common.constant.ResponseEnum.PARAM_FORMAT_ERROR.toResult();
        } catch (Exception e) {
            log.error("完结支付分服务订单失败", e);
            return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("完结失败：" + e.getMessage());
        }
    }

    /**
     * 取消支付分服务订单
     */
    @PostMapping("/cancel")
    public Result<Map<String, Object>> cancelPayScoreOrder(@RequestBody Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 请求取消支付分服务订单", userId);

            Map<String, Object> data = payScoreService.cancelUserPayScoreOrder(userId, params);
            if (data != null) {
                log.info("取消支付分服务订单成功 - orderId: {}", params.get("orderId"));
                return Result.success("取消成功", data);
            } else {
                return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("取消支付分服务订单失败");
            }
        } catch (NumberFormatException e) {
            log.error("参数格式错误", e);
            return com.haha.common.constant.ResponseEnum.PARAM_FORMAT_ERROR.toResult();
        } catch (Exception e) {
            log.error("取消支付分服务订单失败", e);
            return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("取消失败：" + e.getMessage());
        }
    }

    /**
     * 查询支付分服务订单状态（按 outOrderNo 查询）
     * 用于微信支付分授权返回后，判断用户是确认还是取消
     */
    @GetMapping("/query-out-no/{outOrderNo}")
    public Result<Map<String, Object>> queryByOutOrderNo(@PathVariable String outOrderNo) {
        try {
            log.info("按 outOrderNo 查询支付分状态 - outOrderNo: {}", outOrderNo);

            PayScoreResult result = payScoreService.queryPayScoreOrder(outOrderNo);
            if (result.isSuccess()) {
                Map<String, Object> data = new java.util.HashMap<>();
                data.put("outOrderNo", result.getOutOrderNo());
                data.put("state", result.getState());
                log.info("查询成功 - outOrderNo: {}, state: {}", outOrderNo, result.getState());
                return Result.success(data);
            } else {
                return Result.error(result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("查询支付分服务订单失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 查询支付分服务订单状态
     */
    @GetMapping("/query/{orderId}")
    public Result<Map<String, Object>> queryPayScoreOrder(@PathVariable Long orderId) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 查询支付分服务订单状态 - orderId: {}", userId, orderId);

            Map<String, Object> data = payScoreService.queryUserPayScoreOrder(userId, orderId);
            if (data != null) {
                log.info("查询支付分服务订单成功 - orderId: {}", orderId);
                return Result.success("查询成功", data);
            } else {
                return com.haha.common.constant.ResponseEnum.ORDER_NOT_FOUND.toResult("订单不存在或未创建支付分服务订单");
            }
        } catch (Exception e) {
            log.error("查询支付分服务订单失败", e);
            return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("查询失败：" + e.getMessage());
        }
    }

    /**
     * 同步订单支付分状态
     */
    @PostMapping("/sync/{orderId}")
    public Result<Void> syncPayScoreStatus(@PathVariable Long orderId) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 同步支付分状态 - orderId: {}", userId, orderId);

            boolean success = payScoreService.syncUserPayScoreStatus(userId, orderId);
            if (success) {
                log.info("同步支付分状态成功 - orderId: {}", orderId);
                return Result.success("同步成功", null);
            } else {
                return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("同步失败");
            }
        } catch (Exception e) {
            log.error("同步支付分状态失败", e);
            return com.haha.common.constant.ResponseEnum.OPERATION_FAILED.toResult("同步失败：" + e.getMessage());
        }
    }

    /**
     * 修改支付分订单金额（仅 USER_PAYING 状态可下调）
     */
    @PostMapping("/modify")
    public Result<Map<String, Object>> modifyPayScoreOrder(@RequestBody Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 请求修改支付分订单金额", userId);

            if (!params.containsKey("orderId") || !params.containsKey("totalAmount")) {
                return com.haha.common.constant.ResponseEnum.PARAM_FORMAT_ERROR.toResult("缺少必填参数");
            }

            Long orderId = Long.valueOf(params.get("orderId").toString());
            BigDecimal totalAmount = new BigDecimal(params.get("totalAmount").toString());
            String reason = params.containsKey("reason") ? params.get("reason").toString() : "金额调整";

            List<PayScoreModifyRequest.PostPayment> payments = null;
            if (params.containsKey("payments")) {
                payments = com.alibaba.fastjson2.JSON.parseArray(
                        params.get("payments").toString(), PayScoreModifyRequest.PostPayment.class);
            }

            PayScoreResult result = payScoreService.modifyPayScoreOrder(orderId, totalAmount, payments, reason);
            if (result.isSuccess()) {
                Map<String, Object> data = new java.util.HashMap<>();
                data.put("outOrderNo", result.getOutOrderNo());
                data.put("state", result.getState());
                return Result.success("修改成功", data);
            } else {
                return Result.error(result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("修改支付分订单金额失败", e);
            return Result.error("修改失败：" + e.getMessage());
        }
    }

    /**
     * 同步订单支付信息（用户已通过其他方式支付时停止扣款）
     */
    @PostMapping("/sync-info/{orderId}")
    public Result<Map<String, Object>> syncOrderPaidInfo(@PathVariable Long orderId,
                                                          @RequestBody(required = false) Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 请求同步支付分订单支付信息 - orderId: {}", userId, orderId);

            String detail = params != null && params.containsKey("detail") ? params.get("detail").toString() : null;
            PayScoreResult result = payScoreService.syncOrderPaidInfo(orderId, detail);
            if (result.isSuccess()) {
                Map<String, Object> data = new java.util.HashMap<>();
                data.put("outOrderNo", result.getOutOrderNo());
                data.put("state", result.getState());
                return Result.success("同步成功", data);
            } else {
                return Result.error(result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("同步支付分订单支付信息失败", e);
            return Result.error("同步失败：" + e.getMessage());
        }
    }

    /**
     * 支付分退款
     */
    @PostMapping("/refund/{orderId}")
    public Result<Map<String, Object>> refundPayScoreOrder(@PathVariable Long orderId,
                                                            @RequestBody Map<String, Object> params) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 请求支付分退款 - orderId: {}", userId, orderId);

            BigDecimal refundAmount = params.containsKey("refundAmount")
                    ? new BigDecimal(params.get("refundAmount").toString())
                    : null;
            String reason = params.containsKey("reason") ? params.get("reason").toString() : "用户申请退款";

            PayScoreResult result = payScoreService.refundPayScoreOrder(orderId, refundAmount, reason);
            if (result.isSuccess()) {
                Map<String, Object> data = new java.util.HashMap<>();
                data.put("outOrderNo", result.getOutOrderNo());
                data.put("refundId", result.getPackageStr());
                return Result.success("退款申请成功", data);
            } else {
                return Result.error(result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("支付分退款失败", e);
            return Result.error("退款失败：" + e.getMessage());
        }
    }

    /**
     * 查询支付分退款状态
     */
    @GetMapping("/refund/{orderId}/{outRefundNo}")
    public Result<Map<String, Object>> queryPayScoreRefund(@PathVariable Long orderId,
                                                            @PathVariable String outRefundNo) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("用户 {} 查询支付分退款状态 - orderId: {}, refundNo: {}", userId, orderId, outRefundNo);

            PayScoreResult result = payScoreService.queryPayScoreRefund(orderId, outRefundNo);
            if (result.isSuccess()) {
                Map<String, Object> data = new java.util.HashMap<>();
                data.put("outOrderNo", result.getOutOrderNo());
                data.put("status", result.getState());
                data.put("amount", result.getTotalAmount());
                return Result.success("查询成功", data);
            } else {
                return Result.error(result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("查询退款状态失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }

    /**
     * 支付分回调通知
     */
    @SaIgnore
    @PostMapping("/callback")
    public String handleCallback(HttpServletRequest request) {
        try {
            log.info("收到支付分回调通知");

            Map<String, Object> params = RequestParseUtil.parseWechatPayCallbackParams(request);

            PayScoreCallbackResult result = payScoreService.handlePayScoreCallback(params);

            if (result.isSuccess()) {
                log.info("支付分回调处理成功 - outOrderNo: {}, eventType: {}, state: {}",
                        result.getOutOrderNo(), result.getEventType(), result.getState());
                return CallbackConstants.WECHAT_PAYSCORE_SUCCESS;
            } else {
                log.warn("支付分回调处理失败 - errorMsg: {}", result.getErrorMsg());
                return CallbackConstants.WECHAT_PAYSCORE_FAIL;
            }
        } catch (Exception e) {
            log.error("处理支付分回调失败", e);
            return CallbackConstants.WECHAT_PAYSCORE_FAIL;
        }
    }
}
