package org.dromara.system.controller;

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

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.request.WxPayRefundQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.TblDzbcDriverTrip;
import org.dromara.system.domain.vo.SysSocialVo;
import org.dromara.system.domain.vo.TblDzbcPathSchedulingVo;
import org.dromara.system.mapper.TblDzbcDriverTripMapper;
import org.dromara.system.service.ISysSocialService;
import org.dromara.system.service.ITblDzbcPathSchedulingService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
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.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.system.domain.vo.TblDzbcOrderVo;
import org.dromara.system.domain.bo.TblDzbcOrderBo;
import org.dromara.system.service.ITblDzbcOrderService;
import org.dromara.common.mybatis.core.page.TableDataInfo;

/**
 * 定制班车-订单
 *
 * @author Lion Li
 * @date 2025-02-12
 */
@Validated
@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("/system/dzbcOrder")
public class TblDzbcOrderController extends BaseController {

    private final ITblDzbcOrderService tblDzbcOrderService;

    private final ITblDzbcPathSchedulingService tbspSchedulingService;

    private final ISysSocialService sysSocialService;

    private final WxPayService wxPayService;

    private final TblDzbcDriverTripMapper driverTripMapper;

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

    /**
     * 查询定制班车-订单列表
     */

    @GetMapping("/list")
    public TableDataInfo<TblDzbcOrderVo> list(TblDzbcOrderBo bo, PageQuery pageQuery) {
        if(!LoginHelper.getLoginUser().getRoles().stream().map(i->i.getRoleName()).collect(Collectors.joining(",")).contains("定制班车-管理员")){
            bo.setUserId(LoginHelper.getUserId());
        }
        return tblDzbcOrderService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出定制班车-订单列表
     */

    @Log(title = "定制班车-订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(TblDzbcOrderBo bo, HttpServletResponse response) {
        List<TblDzbcOrderVo> list = tblDzbcOrderService.queryList(bo);
        ExcelUtil.exportExcel(list, "定制班车-订单", TblDzbcOrderVo.class, response);
    }

    /**
     * 获取定制班车-订单详细信息
     *
     * @param id 主键
     */

    @GetMapping("/{id}")
    public R<TblDzbcOrderVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        Long userid=null;
        if(!LoginHelper.getLoginUser().getRoles().stream().map(i->i.getRoleName()).collect(Collectors.joining(",")).contains("定制班车-管理员")){
            userid = (LoginHelper.getUserId());
        }
        TblDzbcOrderVo orderVo = tblDzbcOrderService.queryById(id);
        if(userid!=null){
            if(!orderVo.getUserId().equals(userid)){
                return R.fail("您没有权限查看该订单");
            }
        }
        TblDzbcPathSchedulingVo scheduling = tbspSchedulingService.queryById(orderVo.getSchedulingId());
        scheduling.setStartSites(null);
        scheduling.setEndSites(null);
        orderVo.setScheduling(scheduling);

        return R.ok(orderVo);
    }

    /**
     * 新增定制班车-订单
     */

    @Log(title = "定制班车-订单", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R add(@Validated(AddGroup.class) @RequestBody TblDzbcOrderBo bo) {
        try {
            return R.ok(tblDzbcOrderService.insertByBo(bo));
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }

    }

    @Log(title = "定制班车-多站点订单", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/multiSite")
    public R addMultiSite(@Validated(AddGroup.class) @RequestBody TblDzbcOrderBo bo) {
        try {
            TblDzbcPathSchedulingVo scheduling = tbspSchedulingService.queryById(bo.getSchedulingId());
            if (scheduling == null) {
                return R.fail("路线未查询到排班");
            }
            if (scheduling.getType() == null || scheduling.getType() != 2) {
                return R.fail("不是多站点路线排班");
            }
            return R.ok(tblDzbcOrderService.insertByBo(bo));
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    /**
     * 修改定制班车-订单
     */

    @Log(title = "定制班车-订单", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TblDzbcOrderBo bo) {
//        return toAjax(tblDzbcOrderService.updateByBo(bo));
        return R.fail("失败");
    }

    /**
     * 删除定制班车-订单
     *
     * @param ids 主键串
     */

    @Log(title = "定制班车-订单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
//        return toAjax(tblDzbcOrderService.deleteWithValidByIds(List.of(ids), true));
        return R.fail("失败");
    }

    /**
     * 获取定制班车-获取订单微信支付参数
     *
     * @param id 主键
     */
    @Log(title = "定制班车-订单", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @GetMapping("/pay/wx/{id}")
    public R getOrderWxPay(@PathVariable Long id) {
        TblDzbcOrderVo tblDzbcOrderVo = tblDzbcOrderService.queryById(id);
        if (tblDzbcOrderVo == 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(!tblDzbcOrderVo.getUserId().equals(userid)){
                return R.fail("您没有权限查看该订单");
            }
        }
        if (tblDzbcOrderVo.getStatus().equals("0")) {
            try {
                WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
                orderRequest.setBody("定制班车车票");
                orderRequest.setOutTradeNo(tblDzbcOrderVo.getId().toString());
                orderRequest.setTotalFee(tblDzbcOrderVo.getTotalPrice());
                orderRequest.setTradeType("JSAPI");
                orderRequest.setGoodsTag(tblDzbcOrderVo.getName());
                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("该订单无法支付");


        } else {
            return R.fail("该订单无法支付");
        }

    }


    /**
     * 取消定订单
     *
     * @param id 主键
     */
    @Log(title = "定制班车-订单", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @GetMapping("/cancel/{id}")
    public R<Void> cancelOrder(@PathVariable Long id) {
        TblDzbcOrderVo tblDzbcOrderVo = tblDzbcOrderService.queryById(id);
        Long userid=null;
        if(!LoginHelper.getLoginUser().getRoles().stream().map(i->i.getRoleName()).collect(Collectors.joining(",")).contains("定制班车-管理员")){
            userid = (LoginHelper.getUserId());
        }
        if(userid!=null){
            if(!tblDzbcOrderVo.getUserId().equals(userid)){
                return R.fail("您没有权限查看该订单");
            }
        }
        if (tblDzbcOrderVo == null) return R.fail("该订单不存在");
        if (tblDzbcOrderVo.getStatus().equals("1")) {
            // 判断是否为固定路线(type=2)，如果是则检查发车状态
            TblDzbcPathSchedulingVo scheduling = tbspSchedulingService.queryById(tblDzbcOrderVo.getSchedulingId());
            if (scheduling != null && scheduling.getType() != null && scheduling.getType() == 2) {
                // 固定路线：通过 driverTrip 判断发车状态
                TblDzbcDriverTrip trip = driverTripMapper.selectOne(
                    new LambdaQueryWrapper<TblDzbcDriverTrip>()
                        .apply("ext2->'$.schedulingId' = {0}", tblDzbcOrderVo.getSchedulingId())
                        .last("LIMIT 1")
                );
                if (trip != null && trip.getStatus() != null && trip.getStatus() >= 1) {
                    // status: 0-待发车 1-运行中 2-已完成 3-已取消
                    return R.fail("该班次已发车，无法退款");
                }
            }
            //判断订单时间 订单时间距离发车>60分钟可以取消
            double bl = 1;
            try {
                JSONObject json = JSONUtil.parseObj(tblDzbcOrderVo.getExt2()).getJSONObject("schedulInfo");
                Date date = json.getDate("mdate");
                String time = json.getStr("mtime");
                Date date1 = DateUtil.parse(DateUtil.format(date, "yyyy-MM-dd") + " " + time, "yyyy-MM-dd HH:mm:ss");
                if(date1.getTime()-DateUtil.current()>60*60*1000){
                    bl=1;
                }else if(date1.getTime()-DateUtil.current()<60*60*1000 && date1.getTime()-DateUtil.current()>0){
                    bl=0.5;
                }else{
                    return R.fail("该订单已发车，无法取消，请联系管理员");
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("时间转换异常,异常原因{}", e.getMessage());
                return R.fail("该订单无法取消");
            }

//            if (DateUtil.between(new Date(), tblDzbcOrderVo.getCreateTime(), DateUnit.MINUTE) > 30) {
//                return R.fail("该订单无法取消");
//            }
            try {
                log.info(tblDzbcOrderVo.getExt2());
                JSONObject wxtrade = JSONUtil.parseObj(tblDzbcOrderVo.getExt2()).getJSONObject("wxpay");
                log.info(JSONUtil.toJsonStr(wxtrade));
                WxPayRefundRequest refundRequest = new WxPayRefundRequest();
                refundRequest.setTotalFee(tblDzbcOrderVo.getTotalPrice());
                refundRequest.setRefundFee((int)Math.round(tblDzbcOrderVo.getTotalPrice()*bl));
                refundRequest.setOutTradeNo(wxtrade.getStr("outTradeNo"));
                refundRequest.setOutRefundNo(wxtrade.getStr("transactionId"));
                refundRequest.setTransactionId(wxtrade.getStr("transactionId"));
                refundRequest.setNotifyUrl(baseUrl + "/system/commonOther/wx/ref");
                wxPayService.refund(refundRequest);

                TblDzbcOrderBo order1 = new TblDzbcOrderBo();
                order1.setId(tblDzbcOrderVo.getId());
                order1.setStatus("2");
                tblDzbcOrderService.updateByBo(order1);
                return R.ok("成功,发车前1小时可以退50%车费");
            }catch (Exception e){
                e.printStackTrace();
                log.error("时间转换异常,异常原因{}", e.getMessage());
            }
            return R.fail("该订单无法取消");
        }else if(tblDzbcOrderVo.getStatus().equals("0")){
            TblDzbcOrderBo order1 = new TblDzbcOrderBo();
            order1.setId(tblDzbcOrderVo.getId());
            order1.setStatus("5");
            tblDzbcOrderService.updateByBo(order1);
            return R.ok("成功");
        } else{
            return R.fail("该订单无法取消");
        }

    }
}
