package org.dromara.system.controller;

import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.CargoOrderSubmitBo;
import org.dromara.system.domain.bo.TblDzbcCargoOrderBo;
import org.dromara.system.domain.vo.TblDzbcCargoOrderVo;
import org.dromara.system.service.ITblDzbcCargoOrderService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.service.WxPayService;
import org.dromara.system.domain.vo.SysSocialVo;
import org.dromara.system.service.ISysSocialService;
import org.springframework.beans.factory.annotation.Value;

import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/dzbc/cargoOrder")
@Slf4j
public class TblDzbcCargoOrderController extends BaseController {

    private final ITblDzbcCargoOrderService tblDzbcCargoOrderService;
    private final ISysSocialService sysSocialService;
    private final WxPayService wxPayService;

    @Value("${baseUrl}")
    String baseUrl;

    @GetMapping("/list")
    public TableDataInfo<TblDzbcCargoOrderVo> list(TblDzbcCargoOrderBo bo, PageQuery pageQuery) {
        return tblDzbcCargoOrderService.queryPageList(bo, pageQuery);
    }

    @GetMapping("/trip/{tripId}")
    public R<List<TblDzbcCargoOrderVo>> listByTripId(@PathVariable Long tripId) {
        return R.ok(tblDzbcCargoOrderService.queryByTripId(tripId));
    }

    @GetMapping("/my/list")
    public R<List<TblDzbcCargoOrderVo>> myList() {
        Long userId = LoginHelper.getUserId();
        return R.ok(tblDzbcCargoOrderService.queryByUserId(userId));
    }

    @Log(title = "货物订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(TblDzbcCargoOrderBo bo, HttpServletResponse response) {
        List<TblDzbcCargoOrderVo> list = tblDzbcCargoOrderService.queryList(bo);
        ExcelUtil.exportExcel(list, "货物订单", TblDzbcCargoOrderVo.class, response);
    }

    @GetMapping("/{id}")
    public R<TblDzbcCargoOrderVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
        return R.ok(tblDzbcCargoOrderService.queryById(id));
    }

    @Log(title = "提交货物订单", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/submit")
    public R<TblDzbcCargoOrderVo> submit(@Validated @RequestBody CargoOrderSubmitBo bo) {
        return R.ok(tblDzbcCargoOrderService.submitOrder(bo));
    }

    @Log(title = "货物订单", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TblDzbcCargoOrderBo bo) {
        return toAjax(tblDzbcCargoOrderService.updateByBo(bo));
    }

    @Log(title = "更新订单状态", businessType = BusinessType.UPDATE)
    @PostMapping("/status/{id}")
    public R<Void> updateStatus(@NotNull(message = "主键不能为空") @PathVariable Long id,
                                 @NotNull(message = "状态不能为空") @RequestParam Integer status) {
        return toAjax(tblDzbcCargoOrderService.updateStatus(id, status));
    }

    @Log(title = "货物订单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
        return toAjax(tblDzbcCargoOrderService.deleteWithValidByIds(List.of(ids), true));
    }

    /**
     * 获取货物订单-获取订单微信支付参数
     */
    @Log(title = "货物订单-微信支付", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @GetMapping("/pay/wx/{id}")
    public R getOrderWxPay(@PathVariable Long id) {
        TblDzbcCargoOrderVo orderVo = tblDzbcCargoOrderService.queryById(id);
        if (orderVo == null) return R.fail("该订单不存在");

        // 权限校验
        Long userid = null;
        if (!LoginHelper.getLoginUser().getRoles().stream().map(i -> i.getRoleName()).collect(Collectors.joining(",")).contains("定制班车-管理员")) {
            userid = (LoginHelper.getUserId());
        }
        if (userid != null) {
            if (!orderVo.getUserId().equals(userid)) {
                return R.fail("您没有权限查看该订单");
            }
        }

        if (orderVo.getPayStatus() == 0) { // 待支付
            try {
                // 如果价格为0，直接更新为已支付
                if (orderVo.getPrice() == null || orderVo.getPrice() <= 0) {
                    tblDzbcCargoOrderService.updateStatus(id, 0); // 状态保持待发货
                    // 更新支付状态逻辑需要单独处理，或者updateStatus支持
                    // 这里为了简单，假设updateStatus只更新status，我们需要手动更新payStatus
                    // 但Service层没有单独暴露更新payStatus接口，暂时通过bo更新
                    TblDzbcCargoOrderBo updateBo = new TblDzbcCargoOrderBo();
                    updateBo.setId(id);
                    updateBo.setPayStatus(1);
                    tblDzbcCargoOrderService.updateByBo(updateBo);
                    return R.ok("支付成功");
                }

                WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
                orderRequest.setBody("寄车带货运费");
                orderRequest.setOutTradeNo("C" + orderVo.getId().toString()); // 加C前缀区分货物订单
                orderRequest.setTotalFee(orderVo.getPrice());
                orderRequest.setTradeType("JSAPI");
                orderRequest.setGoodsTag("货物运输");
                orderRequest.setNotifyUrl(baseUrl + "/system/commonOther/wx");

                List<SysSocialVo> sysSocials = sysSocialService.queryListByUserId(LoginHelper.getUserId());
                AtomicReference<SysSocialVo> sysSocialVo1 = new AtomicReference<>();
                sysSocials.forEach(sysSocialVo -> {
                    if (sysSocialVo.getSource().equals("WECHAT_MINI_PROGRAM_1")) {
                        sysSocialVo1.set(sysSocialVo);
                    }
                });
                if (sysSocialVo1.get() == null) {
                    return R.fail("该用户未绑定微信小程序");
                }
                orderRequest.setOpenid(sysSocialVo1.get().getOpenId());
                orderRequest.setSpbillCreateIp("127.0.0.1");
                orderRequest.setTimeStart(DateUtil.format(new Date(), "yyyyMMddHHmmss"));
                orderRequest.setTimeExpire(DateUtil.format(DateUtil.offsetMinute(new Date(), 30), "yyyyMMddHHmmss"));

                Object data = wxPayService.createOrder(orderRequest);
                return R.ok(data);

            } catch (Exception w) {
                log.error("微信支付异常,异常原因{}", w.getMessage());
                return R.fail("支付异常：" + w.getMessage());
            }
        } else {
            return R.fail("该订单已支付或无需支付");
        }
    }

    /**
     * 取消货物订单
     */
    @Log(title = "货物订单-取消", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @GetMapping("/cancel/{id}")
    public R<Void> cancelOrder(@PathVariable Long id) {
        TblDzbcCargoOrderVo orderVo = tblDzbcCargoOrderService.queryById(id);
        if (orderVo == null) return R.fail("该订单不存在");

        // 权限校验
        Long userid = null;
        if (!LoginHelper.getLoginUser().getRoles().stream().map(i -> i.getRoleName()).collect(Collectors.joining(",")).contains("定制班车-管理员")) {
            userid = (LoginHelper.getUserId());
        }
        if (userid != null) {
            if (!orderVo.getUserId().equals(userid)) {
                return R.fail("您没有权限操作该订单");
            }
        }

        // 状态校验：只有待发货(0)的订单可以取消
        if (orderVo.getStatus() != 0) {
            return R.fail("当前订单状态无法取消");
        }

        // 已支付订单需要退款
        if (orderVo.getPayStatus() == 1) {
             try {
                 // 查询是否有支付记录，这里假设ext2存了支付回调信息，或者通过outTradeNo去查
                 // 由于目前货物订单表ext2存了价格json，可能没有存支付信息，这里尝试构造退款请求
                 // 更好的方式是在支付回调时把 transactionId 存入 ext2 或新字段
                 // 暂时假设前端或者数据库能提供 transactionId，这里简化处理：
                 // 如果没有transactionId，可能需要通过 outTradeNo 退款

                 String outTradeNo = "C" + orderVo.getId().toString();

                 // 构造退款请求
                 WxPayRefundRequest refundRequest = new WxPayRefundRequest();
                 refundRequest.setTotalFee(orderVo.getPrice());
                 refundRequest.setRefundFee(orderVo.getPrice()); // 全额退款
                 refundRequest.setOutTradeNo(outTradeNo);
                 refundRequest.setOutRefundNo(outTradeNo); // 使用订单号作为退款单号
                 refundRequest.setNotifyUrl(baseUrl + "/system/commonOther/wx/ref");

                 wxPayService.refund(refundRequest);

                 // 更新状态为已取消(4)
                 TblDzbcCargoOrderBo updateBo = new TblDzbcCargoOrderBo();
                 updateBo.setId(id);
                 updateBo.setStatus(4); // 已取消
                 // 退款回调中会处理实际的退款状态，这里先置为取消
                 tblDzbcCargoOrderService.updateByBo(updateBo);

                 return R.ok("订单取消成功，退款处理中");

             } catch (Exception e) {
                 log.error("退款异常", e);
                 return R.fail("取消失败：退款异常");
             }
        } else {
            // 未支付直接取消
            TblDzbcCargoOrderBo updateBo = new TblDzbcCargoOrderBo();
            updateBo.setId(id);
            updateBo.setStatus(4); // 已取消
            tblDzbcCargoOrderService.updateByBo(updateBo);
            return R.ok("订单取消成功");
        }
    }
}
